WooCommerce 後台訂單自訂欄位資料儲存實作說明

前言

在 WooCommerce 訂單後台管理時,常會需要額外新增自訂欄位以收集特定資訊,例如客戶的聯絡電話。這段程式碼示範如何在訂單編輯頁面保存自訂欄位資料,確保資料能正確存入訂單元資料中。適合已熟悉 WooCommerce 且想擴充後台訂單欄位功能的工程師或自學者。

為什麼需要自訂欄位儲存機制

WooCommerce 預設訂單資料結構無法涵蓋所有業務需求,因此經常會透過自訂欄位來擴充。這些欄位必須在後台訂單編輯時能夠被正確讀取與保存,否則資料會遺失。

使用 woocommerce_process_shop_order_meta 鉤子

這個 action 鉤子會在 WooCommerce 處理訂單後台編輯表單時觸發,適合用來攔截並保存自訂欄位資料。

add_action('woocommerce_process_shop_order_meta', function ($order_id) {
    // 權限檢查,避免非授權使用者修改訂單
    if (!current_user_can('edit_shop_order', $order_id))
        return;

    $key = '_shipping_phone'; // 自訂欄位名稱

    // 確認表單有送出該欄位
    if (!isset($_POST[$key]))
        return;

    // 清理輸入資料,避免 XSS 或其他注入風險
    $value = wc_clean(wp_unslash($_POST[$key]));

    // 取得訂單物件
    $order = wc_get_order($order_id);
    if (!$order)
        return;

    // 使用 WC_Order API 更新訂單元資料
    $order->update_meta_data($key, $value);
    $order->save(); // 必須呼叫 save() 才會寫入資料庫
}, 50);

關鍵說明

  • current_user_can 用來確保只有有編輯訂單權限的使用者能執行更新。
  • wc_cleanwp_unslash 是 WordPress 與 WooCommerce 提供的安全函式,確保輸入資料安全。
  • 使用 update_meta_datasave 是 WooCommerce 推薦的寫入方式,兼容新版 HPOS(高效訂單存儲系統)與舊版 postmeta。

實務應用與延伸

此方法可擴充至任何自訂欄位,只要對應修改 $key 與表單名稱即可。實務中,還可搭配後台欄位輸入介面(如使用 woocommerce_admin_order_data_after_billing_address 鉤子)來完整實作自訂欄位的讀寫。

常見問題與注意事項

  • 忘記呼叫 $order->save() 將導致資料無法寫入。
  • 欄位名稱建議加底線開頭避免與 WooCommerce 原生欄位衝突。
  • 權限檢查不可省略,避免安全問題。

完整程式碼

<?php
add_action('woocommerce_process_shop_order_meta', function ($order_id) {
    if (!current_user_can('edit_shop_order', $order_id))
        return;

    $key = '_shipping_phone';

    if (!isset($_POST[$key]))
        return;

    $value = wc_clean(wp_unslash($_POST[$key]));

    $order = wc_get_order($order_id);
    if (!$order)
        return;

    $order->update_meta_data($key, $value);
    $order->save();
}, 50);