背景說明
客戶想做一個物流配送流程,不用套用第三方物流插件,所以我用 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 就能解決了。希望這樣的整理對你有幫助!
