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

WooCommerce订单邮件中get_post_meta()无法生效问题

WooCommerce订单邮件自定义字段不显示(测试插件正常)的排查与修复

问题概述

你遇到的情况是:修改email-order-details.php模板添加自定义字段后,用WooCommerce Email Test插件测试时所有自定义字段都能正常展示,但实际发送的订单邮件里这些字段却无法显示。以下是你用到的核心代码片段:

<tfoot> 
<?php if ( $totals = $order->get_order_item_totals() ) { 
    $i = 0; 
    foreach ( $totals as $total ) { 
        $i++; ?> 
        <?php if($total['label'] == "Shipping:" || $total['label'] == "Verzending:"){ ?> 
        <?php } elseif($total['label'] == "Subtotal:" || $total['label'] == "Subtotaal:") { 
            $oid = $order->get_id(); ?> 
            <tr> 
                <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Subtotaal"; ?></th> 
                <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">
                    <?php $order_st=get_post_meta($oid, 'order_subtotal', true); echo "<span class='woocommerce-Price-currencySymbol'>".get_woocommerce_currency_symbol()."</span>".$order_st."245.00"; ?>
                </td> 
            </tr> 
            <?php $trans_method=get_post_meta($oid, 'trans_method', true); 
            if($trans_method == 'pickup'){ ?> 
                <tr> 
                    <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Transportkosten"; ?></th> 
                    <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "<span class='woocommerce-Price-currencySymbol'>".get_woocommerce_currency_symbol()."</span>0.00"; ?></td> 
                </tr> 
                <tr> 
                    <td colspan="2" class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Afhalen"; ?></td> 
                </tr> 
                <tr> 
                    <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Totaal ex BTW"; ?></th> 
                    <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">
                        <?php $teb=get_post_meta($oid, 'order_subtotal', true); echo "<span class='woocommerce-Price-currencySymbol'>".get_woocommerce_currency_symbol()."</span>".$teb; ?>
                    </td> 
                </tr> 
            <?php } ?> 
            <?php if($trans_method == 'deliverybypostcode'){ ?> 
                <tr> 
                    <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Transportkosten"; ?></th> 
                    <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">
                        <span class="woocommerce-Price-currencySymbol"><?php $transcost=get_post_meta($oid, 'tran_cost', true); echo get_woocommerce_currency_symbol(); ?></span><?php echo money_format("%.2n", $transcost); ?>
                    </td> 
                </tr> 
                <tr>
                    <td colspan="2" class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">
                        <?php echo "Bezorgen op postcode:"; ?> 
                        <?php $postcode=get_post_meta($oid, 'trans_location', true); $place_dis=get_post_meta($oid, 'trans_distance', true); $mcrane=get_post_meta($oid, 'mounted_crane', true); echo $postcode[0]." ".$place_dis."</br>"; 
                        if($mcrane == "Yes"){ echo "Transport: "."Met autolaadkraan"."</td></tr>"; }else{ echo "Transport: "."Zonder autolaadkraan"."</td></tr>"; } ?> 
                <tr> 
                    <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo "Totaal ex BTW"; ?></th> 
                    <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">
                        <?php $os_total=get_post_meta($oid, 'order_subtotal', true); $tcost=get_post_meta($oid, 'tran_cost', true); $ot_cost=$os_total+money_format("%.2n", $tcost); echo "<span class='woocommerce-Price-currencySymbol'>".get_woocommerce_currency_symbol()."</span>". money_format("%.2n", $ot_cost); ?>
                    </td> 
                </tr> 
            <?php } ?> 
        <?php } elseif($total['label'] == "BTW:"){ 
            $oid1 = $order->get_id(); ?> 
            <tr> 
                <th class="td" scope="row" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>"><?php echo $total['label']; ?></th> 
                <td class="td" style="text-align:<?php echo $text_align; ?>; <?php echo ( 1 === $i ) ? 'border-top-width: 4px;' : ''; ?>">

核心问题排查与修复方案

1. 自定义字段存储时机不对

测试插件一般用的是已经保存好自定义字段的历史订单,但新订单创建时,你的自定义字段可能还没被写入数据库的post_meta表中。

  • 修复:用WooCommerce的钩子确保字段在订单创建时保存,比如woocommerce_checkout_update_order_meta:
add_action('woocommerce_checkout_update_order_meta', 'save_custom_order_fields', 10, 1);
function save_custom_order_fields($order_id) {
    // 保存运输方式
    if(isset($_POST['trans_method'])){
        update_post_meta($order_id, 'trans_method', sanitize_text_field($_POST['trans_method']));
    }
    // 同理保存其他字段:order_subtotal、tran_cost、trans_location等
}

2. 依赖订单总计标签的逻辑不可靠

你的代码靠判断$total['label']的精确值(比如"Subtotal:")来触发逻辑,但实际邮件中,标签可能因为语言设置、WooCommerce版本、甚至空格差异导致判断失效。

  • 修复:改用订单总计的key判断,这是更稳定的方式:
// 替换原来的label判断为key判断
elseif($total['key'] == 'cart_subtotal') { // 购物车小计的固定key是cart_subtotal
    $oid = $order->get_id();
    // 后续逻辑不变
}
// BTW对应的固定key是tax
elseif($total['key'] == 'tax') {
    $oid1 = $order->get_id();
    // 后续逻辑不变
}

3. money_format函数兼容性问题

money_format在Windows服务器环境下是不支持的,会导致代码执行中断,进而无法显示后续字段。

  • 修复:改用WooCommerce内置的wc_price()函数,它兼容所有环境且符合WooCommerce的格式规范:
// 替换运输成本的格式化代码
$transcost = get_post_meta($oid, 'tran_cost', true);
echo wc_price($transcost); // 自动处理货币符号和小数位数

// 总计计算也改用wc_price
$os_total = get_post_meta($oid, 'order_subtotal', true);
$tcost = get_post_meta($oid, 'tran_cost', true);
$ot_cost = $os_total + $tcost;
echo wc_price($ot_cost);

4. 模板重载与缓存问题

确保你修改的是子主题里的email-order-details.php(核心文件修改会被WooCommerce更新覆盖),同时清除网站缓存和邮件服务缓存,确保新模板生效。

5. 订单对象获取方式优化

在某些邮件场景中,$order可能不是完整的WC_Order实例,建议用wc_get_order()获取可靠的订单对象,同时用get_meta()替代get_post_meta():

$order_id = $order->get_id();
$order = wc_get_order($order_id); // 确保获取完整订单对象
$trans_method = $order->get_meta('trans_method'); // 更推荐的WooCommerce字段获取方式

额外建议

尽量避免直接修改邮件模板,改用WooCommerce的woocommerce_email_order_details钩子添加自定义内容,这样既灵活又不会被核心更新覆盖:

add_action('woocommerce_email_order_details', 'add_custom_fields_to_order_email', 20, 4);
function add_custom_fields_to_order_email($order, $sent_to_admin, $plain_text, $email){
    $trans_method = $order->get_meta('trans_method');
    if($trans_method == 'pickup'){
        echo '<tr>
                <th>Transportkosten</th>
                <td>'.wc_price(0.00).'</td>
              </tr>';
        // 其他自定义内容
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:02