You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在WooCommerce邮件通知中显示多组自定义字段

问题描述

我已根据客户购买1件或2件特定商品的情况创建了自定义结账字段,字段包括:Voorletters(名字首字母)、Roepnaam(昵称)、Achternaam(姓氏)和Geboortedatum(出生日期)。目前代码可正常运行,数据已显示在WordPress后台对应订单下方,但希望将这些字段内容添加至两类邮件中:

  • 客户支付成功后收到的订单完成邮件
  • 管理员收到的新订单确认邮件

基于Stack Overflow相关方案,我的现有代码如下:

// 工具函数:获取特定商品的购物车总数量
function get_specific_cart_item_quantity() {
    $targeted_id = 5027; // <== 要检查的商品ID
    $item_qty    = 0; // 初始化

    // 遍历购物车商品
    foreach ( WC()->cart->get_cart() as $item ) {
        if ( $item['product_id'] == $targeted_id ) {
            $item_qty += $item['quantity'];
        }
    }
    return $item_qty;
}

// 添加自定义结账字段
add_action('woocommerce_checkout_before_customer_details', 'add_custom_checkout_fields');
function add_custom_checkout_fields() {
    $item_qty = get_specific_cart_item_quantity();
    
    if ( $item_qty ) {
        $domain  = 'woocommerce';

        echo '<div id="custom_checkout_fields">
            <h3>' . __('<b>Persoonsgegevens BHV</b>', $domain) . '</h3>
            <p>' . __('Vul a.u.b. de persoonsgegevens van de BHV kandidaten in hieronder.', $domain) . '</p>
            <div class="custom-fields-container">';
        
        $qty1 = $item_qty % 2 == 0 ? $item_qty / 2 : ( $item_qty == 1 ? 1 : ($item_qty + 1) / 2 );
        $qty2 = $item_qty == 1 ? 1 : 2;

        // 根据商品数量,以两列布局显示自定义字段的多循环
        for ( $k = 1; $k <= $qty1; $k++ ) {
            $qty2 = $item_qty % 2 != 0 && $k == $qty1 ? 1 : 2;

            // 第二层循环(字段类型)
            foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
                $key = strtolower($letter);

                // 第三层循环(列)
                for ( $h = 1; $h <= $qty2; $h++ ) {
                    $class = $item_qty > 1 ? (($h % 2 == 0) ? 'last' : 'first' ) : 'wide';
                    $class = $item_qty % 2 != 0 && $k == $qty1 ? 'wide' : $class;

                    $index = $item_qty == 1 ? 1 : 2;
                    $index = in_array($class, ['first', 'wide']) ? ($k*2)-1 : $k*2;

                    $field = "custom_field_{$key}{$index}";
                    $label = sprintf('%s %d %s', __('Kandidaat', $domain), $index, $letter);
                
                    woocommerce_form_field( $field, array(
                        'type'          => 'text',
                        'label'         => $label,
                        'placeholder'   => '',
                        'class'         => array('custom-field form-row-'.$class),
                        'required'      => true, // 可改为false
                    ), WC()->checkout->get_value( $field ) );
                }
            }
        }
        echo '</div></div>';
    }
}

// 验证自定义字段
add_action( 'woocommerce_after_checkout_validation', 'validate_custom_checkout_fields', 10, 2 );
function validate_custom_checkout_fields( $data, $errors ) {
    if ( did_action('woocommerce_checkout_process') >= 2 ) return;

    $item_qty = get_specific_cart_item_quantity();

    if ( $item_qty ) {
        $domain   = 'woocommerce';
        $break    = false;

        // 第一层循环(字段类型)
        foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
            $key   = strtolower($letter);

            // 第二层循环(候选人序号)
            for ( $i = 1; $i <= $item_qty; $i++ ) {
                $field = "custom_field_{$key}{$i}";
                
                if ( isset($_POST[$field]) && empty($_POST[$field]) ) {
                    $errors->add( 'validation', __('Vul a.u.b. de verplichte velden in.', $domain), 'error' );
                    $break = true;
                    break;
                }
            }
            if ( $break ) break;
        }
    }
}

// 保存自定义字段数据为订单元数据
add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_fields', 10, 2 );
function save_custom_checkout_fields( $order, $data ) {
    $item_qty = get_specific_cart_item_quantity();

    if ( $item_qty ) {
        // 第一层循环(字段类型)
        foreach ( array('Voorletters', 'Roepnaam', 'Achternaam', 'Geboortedatum') as $letter ) {
            $key   = strtolower($letter);

            // 第二层循环(候选人序号)
            for ( $i = 1; $i <= $item_qty; $i++ ) {
                $field = "custom_field_{$key}{$i}";
                
                if ( isset($_POST[$field]) && ! empty($_POST[$field]) ) {
                    $order->update_meta_data( $field, sanitize_text_field($_POST[$field]) );
                }
            }
        }
    }
}
解决方案:添加自定义字段到邮件中

添加以下代码到你的主题functions.php文件或自定义插件中,即可将自定义字段内容插入到指定邮件的订单详情区域:

// 工具函数:获取订单中特定商品的总数量
function get_specific_order_item_quantity( $order ) {
    $targeted_id = 5027; // 对应之前的商品ID
    $item_qty    = 0;

    // 遍历订单商品
    foreach ( $order->get_items() as $item ) {
        if ( $item->get_product_id() == $targeted_id ) {
            $item_qty += $item->get_quantity();
        }
    }
    return $item_qty;
}

// 将自定义字段添加到邮件订单详情中
add_action('woocommerce_email_order_details', 'add_custom_fields_to_woocommerce_emails', 20, 4);
function add_custom_fields_to_woocommerce_emails( $order, $sent_to_admin, $plain_text, $email ) {
    // 仅针对目标邮件类型:新订单(管理员)和订单完成(客户)
    $targeted_emails = array('new_order', 'customer_completed_order');
    if ( !in_array($email->id, $targeted_emails) ) return;

    $item_qty = get_specific_order_item_quantity( $order );
    if ( !$item_qty ) return;

    $domain = 'woocommerce';
    $fields = array(
        'voorletters' => __('Voorletters', $domain),
        'roepnaam'    => __('Roepnaam', $domain),
        'achternaam'  => __('Achternaam', $domain),
        'geboortedatum' => __('Geboortedatum', $domain)
    );

    // 输出标题
    echo '<h2>' . __('Persoonsgegevens BHV', $domain) . '</h2>';
    echo '<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: \'Helvetica Neue\', Helvetica, Roboto, Arial, sans-serif;">';

    // 按候选人序号循环输出字段
    for ( $i = 1; $i <= $item_qty; $i++ ) {
        echo '<tr><th colspan="2" style="text-align:left; font-size:16px; padding-top:15px;">' . sprintf(__('Kandidaat %d', $domain), $i) . '</th></tr>';
        
        foreach ( $fields as $key => $label ) {
            $meta_key = "custom_field_{$key}{$i}";
            $value = $order->get_meta($meta_key);
            
            if ( !empty($value) ) {
                echo '<tr>
                    <th style="text-align:left; width: 30%;">' . $label . ':</th>
                    <td style="text-align:left;">' . esc_html($value) . '</td>
                </tr>';
            }
        }
    }

    echo '</table>';
}

说明

  • 代码会先判断当前邮件类型是否为目标邮件(新订单/订单完成),再获取订单中对应商品的数量
  • 以表格形式将每个候选人的四个字段有序展示在邮件中,兼容HTML邮件格式
  • 仅当订单中存在目标商品时才会显示该部分内容

内容的提问来源于stack exchange,提问作者TvCasteren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:10:35