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

如何在WooCommerce后台订单中查看自定义产品字段?

WooCommerce自定义字段后台订单不显示问题排查

问题描述

我在未使用插件的情况下,给WooCommerce产品页面添加了3个用户字段(日期字段、文本框、文本域),这些字段能正常显示在购物车和结账页面的商品名称下方,但在后台订单中完全找不到这些元字段的内容。我想知道最后一个用于后台显示的函数存在什么错误?

我的完整代码如下:

// Display custom fields on product page
add_action('woocommerce_before_add_to_cart_button', 'add_custom_fields', 9);
function add_custom_fields() {
    global $product;

    // Define the categories to exclude
    $excluded_categories = array(24, 26);

    // Check if the product belongs to the excluded categories
    if (has_term($excluded_categories, 'product_cat', $product->get_id())) {
        return; // Do not add the fields if the product belongs to the excluded categories
    }

    echo '<div class="customer-fields">';
    echo '<div class="customer-field delivery_date">';
    echo '<label for="delivery_date">Delivery Date<span class="req">*</span>:</label>';
    echo '<input type="date" id="delivery_date" name="delivery_date">';
    echo '</div>';

    echo '<div class="customer-field occasion">';
    echo '<label for="occasion">Occasion:</label>';
    echo '<input type="text" id="occasion" name="occasion" placeholder="Occasion">';
    echo '</div>';

    echo '<div class="customer-field custom_note">';
    echo '<label for="custom_note">Enter Your Message:</label>';
    echo '<textarea id="custom_note" name="custom_note" rows="4" cols="50" placeholder="Enter your message here..."></textarea>';
    echo '</div>';
    echo '</div>';
}

// Save custom fields data to order meta
add_action('woocommerce_add_to_cart', 'save_custom_fields', 10, 2);
function save_custom_fields($cart_item_key, $product_id) {
    if (isset($_POST['delivery_date'])) {
        WC()->session->set('delivery_date', sanitize_text_field($_POST['delivery_date']));
    }
    if (isset($_POST['occasion'])) {
        WC()->session->set('occasion', sanitize_text_field($_POST['occasion']));
    }
    if (isset($_POST['custom_note'])) {
        WC()->session->set('custom_note', sanitize_text_field($_POST['custom_note']));
    }
}

add_action('woocommerce_checkout_create_order_line_item', 'add_custom_fields_to_order_items', 10, 4);
function add_custom_fields_to_order_items($item, $cart_item_key, $values, $order) {
    if (WC()->session->__isset('delivery_date')) {
        $item->add_meta_data('Delivery Date', WC()->session->get('delivery_date'));
        WC()->session->__unset('delivery_date');
    }
    if (WC()->session->__isset('occasion')) {
        $item->add_meta_data('Occasion', WC()->session->get('occasion'));
        WC()->session->__unset('occasion');
    }
    if (WC()->session->__isset('custom_note')) {
        $item->add_meta_data('Custom Note', WC()->session->get('custom_note'));
        WC()->session->__unset('custom_note');
    }
}

// Display custom fields in cart and checkout
add_filter('woocommerce_get_item_data', 'display_custom_fields_in_cart', 10, 2);
function display_custom_fields_in_cart($item_data, $cart_item) {
    if (isset($cart_item['delivery_date'])) {
        $item_data[] = array(
            'key'     => __('Delivery Date', 'woocommerce'),
            'value'   => wc_clean($cart_item['delivery_date']),
            'display' => '',
        );
    }
    if (isset($cart_item['occasion'])) {
        $item_data[] = array(
            'key'     => __('Occasion', 'woocommerce'),
            'value'   => wc_clean($cart_item['occasion']),
            'display' => '',
        );
    }
    if (isset($cart_item['custom_note'])) {
        $item_data[] = array(
            'key'     => __('Custom Note', 'woocommerce'),
            'value'   => wc_clean($cart_item['custom_note']),
            'display' => '',
        );
    }
    return $item_data;
}

// Display custom fields in admin order page
add_action('woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin_order', 10, 1);
function display_custom_fields_in_admin_order($order) {
    $items = $order->get_items();
    foreach ($items as $item_id => $item) {
        $delivery_date = wc_get_order_item_meta($item_id, 'Delivery Date', true);
        $occasion = wc_get_order_item_meta($item_id, 'Occasion', true);
        $custom_note = wc_get_order_item_meta($item_id, 'Custom Note', true);

        if (!empty($delivery_date)) {
            echo '<p><strong>' . __('Delivery Date', 'woocommerce') . ':</strong> ' . $delivery_date . '</p>';
        }
        if (!empty($occasion)) {
            echo '<p><strong>' . __('Occasion', 'woocommerce') . ':</strong> ' . $occasion . '</p>';
        }
        if (!empty($custom_note)) {
            echo '<p><strong>' . __('Custom Note', 'woocommerce') . ':</strong> ' . $custom_note . '</p>';
        }
    }
}

我还尝试过这段代码,但依然无效:

add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_value_admin_order', 10, 1 );
function display_custom_fields_value_admin_order( $order ){

    // Display the delivery date
    if( $delivery_date = $order->get_meta('delivery_date') )
        echo '<p><strong>'.__('Delivery Date').':</strong> ' . $delivery_date . '</p>';
}

错误分析与修正方案

核心错误点

  1. 购物车项数据未同步:
    你在save_custom_fields函数中只把字段值存在了Session,但没有同步到购物车项(cart_contents)里,这导致woocommerce_get_item_data能显示内容是偶然情况,实际购物车项并没有存储这些值,后续流程存在数据断层。

  2. 后台读取元数据的键名错误:
    当你用$item->add_meta_data('Delivery Date', $value)存储订单项元数据时,WooCommerce会自动将带空格的键名转换为下划线格式,并添加前缀_(比如Delivery Date会变成_delivery_date)。你后台读取时用原键名Delivery Date,自然找不到对应值。

  3. 订单元数据读取逻辑错误:
    你尝试的第二段代码用$order->get_meta('delivery_date')读取,但你的字段是存储在**订单项(order line item)**里,不是订单本身的元数据,所以从订单对象读取必然为空。

修正后的完整代码

1. 修正字段存储逻辑(同步到购物车项)

// 保存自定义字段到购物车项和Session
add_action('woocommerce_add_to_cart', 'save_custom_fields', 10, 2);
function save_custom_fields($cart_item_key, $product_id) {
    $cart_item_data = array();
    
    if (isset($_POST['delivery_date'])) {
        $delivery_date = sanitize_text_field($_POST['delivery_date']);
        WC()->session->set('delivery_date', $delivery_date);
        $cart_item_data['delivery_date'] = $delivery_date;
    }
    if (isset($_POST['occasion'])) {
        $occasion = sanitize_text_field($_POST['occasion']);
        WC()->session->set('occasion', $occasion);
        $cart_item_data['occasion'] = $occasion;
    }
    if (isset($_POST['custom_note'])) {
        // 文本域用sanitize_textarea_field保留换行格式
        $custom_note = sanitize_textarea_field($_POST['custom_note']);
        WC()->session->set('custom_note', $custom_note);
        $cart_item_data['custom_note'] = $custom_note;
    }
    
    // 更新购物车项数据
    if (!empty($cart_item_data)) {
        WC()->cart->cart_contents[$cart_item_key] = array_merge(WC()->cart->cart_contents[$cart_item_key], $cart_item_data);
    }
}

2. 修正订单项元数据存储(使用规范键名)

// 将自定义字段添加到订单项
add_action('woocommerce_checkout_create_order_line_item', 'add_custom_fields_to_order_items', 10, 4);
function add_custom_fields_to_order_items($item, $cart_item_key, $values, $order) {
    // 直接从购物车项取数,避免Session依赖
    if (isset($values['delivery_date'])) {
        // 使用下划线键名,第三个参数true表示隐藏元数据(不在前台订单显示)
        $item->add_meta_data('_delivery_date', $values['delivery_date'], true);
    }
    if (isset($values['occasion'])) {
        $item->add_meta_data('_occasion', $values['occasion'], true);
    }
    if (isset($values['custom_note'])) {
        $item->add_meta_data('_custom_note', $values['custom_note'], true);
    }
}

3. 修正后台订单显示逻辑

// 后台订单页面显示自定义字段
add_action('woocommerce_admin_order_data_after_billing_address', 'display_custom_fields_in_admin_order', 10, 1);
function display_custom_fields_in_admin_order($order) {
    foreach ($order->get_items() as $item) {
        // 使用订单项对象的get_meta方法读取规范键名
        $delivery_date = $item->get_meta('_delivery_date');
        $occasion = $item->get_meta('_occasion');
        $custom_note = $item->get_meta('_custom_note');

        if (!empty($delivery_date)) {
            echo '<p><strong>' . __('Delivery Date', 'woocommerce') . ':</strong> ' . esc_html($delivery_date) . '</p>';
        }
        if (!empty($occasion)) {
            echo '<p><strong>' . __('Occasion', 'woocommerce') . ':</strong> ' . esc_html($occasion) . '</p>';
        }
        if (!empty($custom_note)) {
            echo '<p><strong>' . __('Custom Note', 'woocommerce') . ':</strong> ' . esc_html($custom_note) . '</p>';
        }
    }
}

额外优化建议

  • 添加必填字段验证:在woocommerce_add_to_cart_validation钩子中检查delivery_date是否填写,避免空值提交。
  • 前端字段样式优化:给自定义字段添加必要的CSS样式,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:25:53