背景說明

客戶想做一個物流配送流程,不用套用第三方物流插件,所以我用 JetEngine 的 Metabox 擴充 WooCommerce 訂單頁面,新增一個自訂欄位記錄「配送狀態」,同時也把狀態切換的資訊寫入訂單備註。

為了方便管理,我在 WooCommerce 訂單列表頁也加了一欄 「配送狀態」來顯示這個自訂欄位的內容。

遇到的問題

幾天前我開始用 WooCommerce 的 高性能訂單存儲(HPOS),想直接在新專案用新的框架。結果發現過去寫在 Code Snippets 裡面,用來顯示自訂欄位的程式碼完全失效了。

我原本的程式碼是這樣:

php

// 新增「配送狀態」欄位到訂單列表

add_filter(‘manage_woocommerce_page_wc-orders_columns’, function($columns) {

    $columns[‘order_shipping_status’] = __(‘配送狀態’, ‘woocommerce’);

    return $columns;

}, 20);

// 顯示欄位內容

add_action(‘manage_woocommerce_page_wc-orders_custom_column’, function($column, $post_id) {

    if ($column === ‘order_shipping_status’) {

        $order = wc_get_order($post_id);

        if (!$order) {

            echo ”;

            return;

        }

        $value = $order->get_meta(‘order_shipping_status’);

        echo esc_html($value ? $value : ”);

    }

}, 10, 2);

雖然欄位有出現,但資料卻不見了。

當時我問過不少 AI 問題,也試了很多寫法,但因為沒用「HPOS」去關鍵字查,AI 多半給的還是舊版本的語法,無法用。

後來透過關鍵 Hook 名稱反查,才發現這是 HPOS 和舊 Hook 衝突的問題。

解決方案

根據 WordPress 論壇一篇討論(來源:https://wordpress.org/support/topic/high-performance-order-conflict-with-hook-manage_shop_order_posts_custom_column/),Barry 有提醒說在 HPOS 環境下,要改用另一組 Hook。

他建議的寫法是:

php

add_filter( ‘woocommerce_shop_order_list_table_columns’, function ( $columns ) {

    $columns[‘custom_column’] = ‘My Custom Column’;

    return $columns;

} );

add_action( ‘woocommerce_shop_order_list_table_custom_column’, function ( $column, $order ) {

    if ( ‘custom_column’ !== $column ) {

        return;

    }

    echo esc_html( ‘Custom value for order #’ . $order->get_id() );

}, 10, 2 );

也就是新的欄位跟內容輸出 Hook 改成 woocommerce_shop_order_list_table_columns 和 woocommerce_shop_order_list_table_custom_column,而且第二個 Hook 會直接傳入 $order 物件,比較方便。

我改寫後的程式碼如下:

php

// 新增「配送狀態」欄位

add_filter(‘woocommerce_shop_order_list_table_columns’, function($columns) {

    $columns[‘order_shipping_status’] = __(‘配送狀態’, ‘woocommerce’);

    return $columns;

});

// 顯示「配送狀態」內容

add_action(‘woocommerce_shop_order_list_table_custom_column’, function($column, $order) {

    if ($column === ‘order_shipping_status’) {

        $note = get_last_shipping_status_note($order->get_id());

        // 用正則取「變更為『』」中間的文字

        if (preg_match(‘/變更為「([^」]+)」/’, $note, $matches)) {

            echo esc_html($matches[1]);  // 顯示狀態,如「待出貨」

        } else {

            echo ”;

        }

    }

}, 10, 2);

// 幫助函式取得訂單最後一則包含「配送狀態」的備註

function get_last_shipping_status_note($order_id) {

    $notes = wc_get_order_notes([

        ‘order_id’ => $order_id,

        ‘orderby’ => ‘date_created’,

        ‘order’ => ‘DESC’,

    ]);

    if (!empty($notes)) {

        foreach ($notes as $note) {

            if (strpos($note->content, ‘配送狀態’) !== false) {

                return wp_kses_post($note->content);

            }

        }

    }

    return ”;

}

這樣改寫後:

  • 自訂欄位欄位名稱能正常顯示在訂單列表
  • 也能從訂單備註正確解析並顯示最新的物流狀態

小結

WooCommerce 開啟 HPOS(高性能訂單存儲) 後,自訂欄位相關 Hook 全改了,舊 Hook 會顯示欄位但不會印出內容,所以無法取得 meta 或自訂欄位資料。

要在訂單列表頁新增欄位顯示自訂資料,必須改用 woocommerce_shop_order_list_table_columns 跟 woocommerce_shop_order_list_table_custom_column 這兩個新 Hook。

此外,woocommerce_shop_order_list_table_custom_column 會直接給 $order 物件,不需再用 post ID 手動取得,寫法也更乾淨。

這也是為什麼你的舊程式碼因為 HPOS 啟用而失效的原因,改用新 Hook 就能解決了。希望這樣的整理對你有幫助!

Leave a Reply

Your email address will not be published. Required fields are marked *