WooCommerce修改結帳欄位的方法

在WordPress中用程式的方法來修改WooCommerce的結帳欄位(新增自訂欄位或是刪除掉預設欄位)

1. 修改結帳欄位

使用到 woocommerce_checkout_fields 這個filter hook,hook上的function會接收到所有結帳欄位的資訊

以下為新增台灣手機號碼帳單欄位為例:

<?php
add_filter('woocommerce_checkout_fields', 'octopuswp_add_checkout_mobile_number');
/**
 * 新增台灣手機號碼,移除預設電話欄位
 * @params array $fields
 */
function octopuswp_add_checkout_mobile_number($fields)
{
    // 移除預設電話欄位
    // unset($fields['billing']['billing_phone']);
    /**
     * $fields記錄著所有的結帳欄位資訊
     * 這裡手機號碼欄位的key值使用billing_mobile_number
     */
    $fields['billing']['billing_mobile_number'] = [
        'text'     => 'text',  //欄位類型
        'label'    => '手機號碼', //標籤
        'required' => true, //必填
        'class'    => ['form-row-wide'] // 全寬欄位的class
    ];
    return $fields;
}
?>

$field的結構為

Array
(
    [billing] => Array
        (
            [billing_first_name] => Array
                (
                    [label] => 名字
                    [required] => 1
                    [class] => Array
                        (
                            [0] => form-row-wide
                        )

                    [autocomplete] => given-name
                    [priority] => 0
                )

            [billing_email] => ...
            [billing_country] => ...
            [billing_phone] => ...
        )

    [shipping] => Array
        (
            [shipping_first_name] => ...
            [shipping_last_name] => ...
            [shipping_company] => ...
            [shipping_country] => ...
            [shipping_address_1] => ...
            [shipping_address_2] => ...
            [shipping_city] => ...
            [shipping_state] => ...
            [shipping_postcode] => ...
        )

    [account] => Array
        (
            [account_username] => ...
            [account_password] => ...

        )

    [order] => Array
        (
            [order_comments] => ...

        )

)

為多層陣列結構,第一層依欄位群組分成

  • billing(帳單資訊)
  • shipping(運送資訊)
  • account(帳號資訊)
  • order(訂單其他資訊)

第二層開始紀錄的就是各欄位的詳細資訊了,第二層的key也是最後會寫進資料庫的key名稱,如key為billing_first_name,最後會寫進資料庫的meta_key就會是_billing_first_name

各個欄位的參數有

  • id:html的id,預設為欄位的key值
  • type:類型,預設為text,可接受的值有country、state、textarea、checkbox、text、password、datetime、datetime-local、date、month、time、week、number、email、url、tel、select、radio
  • label:標籤名稱,會顯示在欄位上方
  • description:補充說明
  • placeholder:欄位內placeholder
  • maxlength:html的maxlength屬性值
  • required:是否必填
  • autocomplete:html的autocomplete屬性值
  • validate:驗證格式(陣列),可接受的值有,postcode、email、phone、state
  • class:欄位的容器class(陣列)
    在結帳欄位中欄位(input、select)及label會被包上一個p標籤容器,class預設可控制這個欄位的排列方式
    控制排列方式的class有form-row-wide(全寬)form-row-first(左欄)form-row-last(右欄)
    也可帶入自訂的class名稱
  • label_class:label的class(陣列)
  • input_class:欄位的class(陣列)
  • options:選項(陣列),若欄位為select或radio,則須帶入
  • custom_attributes:其他自訂的html屬性(陣列)
  • default:預設值,當使用者第一次結帳時的值
  • autofocus:html的autofocus屬性值

欄位資訊最後會透過woocommerce_form_field這個function來產生html,詳細用法請參考

2. 將自訂的結帳欄位顯示在感謝頁面

感謝頁面的hook有很多,依照想顯示出來的地方挑選一個即可(參考woocommerce/tamplates/checkout/thankyou.php),這裡使用woocommerce_before_thankyou這個action hook

範例:

add_action('woocommerce_before_thankyou', 'octopuswp_show_mobile_number_in_thankyou');
/**
 * 將結帳時手機號碼資料顯示在感謝頁面
 * @param int $order_id 訂單ID
 */
function octopuswp_show_mobile_number_in_thankyou($order_id)
{
    $order = wc_get_order($order_id);
    echo '<p>手機號碼:' . $order->get_meta('_billing_mobile_number') . '</p>'; // echo出html結構
}

呈現的效果如下:

 

但這樣看起來怪怪的,因為手機號碼須融入原有感謝頁面的資訊才對,注意到下面有個區塊是顯示帳單資訊的

經查他是透過WC_Order::get_formatted_billing_address這個method產出的html,這是WooCommerce拿來顯示格式化帳單資料html的方法,他會根據不同的國家而有不一樣的顯示方式

而這裡修改的方法有兩種:

第一種是比較遵守遊戲規則,遵照修改格式資料的方式,修改html的顯示格式,讓WooCommerce自己依照格式將資料塞入產出html,範例如下:

參考WC_Countries::get_formatted_address,先修改台灣的html格式,格式預設是定義在WC_Countries::get_address_formats,最後會經過woocommerce_localisation_address_formats這個filter hook

add_filter('woocommerce_localisation_address_formats', 'octopuswp_override_tw_address_format');
/**
 * 修改台灣地址格式
 * @param array $formats
 * @return array mixed
 */
function octopuswp_override_tw_address_format($formats)
{
    $default_tw_address_format = $formats['TW'];
    // 預設的台灣地區地址格式資料,這裡有許多格式字串,WooCommerce會再取代成真正的資料
    // {company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}
    // 在這裡把它放在country的後面,所以直接append上去就好,格式字串自訂
    $formats['TW'] = $default_tw_address_format . "\n{mobile_number}";
    return $formats;
}

接著資料本身是會透過WC_Order::get_address('billing')來傳入,透過woocommerce_get_order_address這個filter hook來將儲存的手機號碼資料加入

add_filter('woocommerce_get_order_address', 'octopuswp_add_order_address_data', 10, 3);
/**
 * 將手機號碼加入地址資料
 * @param array $data 地址資料
 * @param string $type 帳單或運送
 * @param WC_Order $order
 * @return array
 */
function octopuswp_add_order_address_data($data, $type, $order)
{
    // 只有加入帳單的資料
    if('billing' == $type) {
        $data['mobile_number'] = $order->get_meta('_billing_mobile_number');
    }
    return $data;
}

再來就是定義自訂格式字串{mobile_number}要被取代成什麼資料

add_filter('woocommerce_formatted_address_replacements', 'octopuswp_add_address_format_replacement', 10, 2);
/**
 * 加入自訂格式字串的陣列取代資料
 * @param array $replacements 要取代的字串對應陣列
 * @param array $data 地址資料
 * @return mixed
 */
function octopuswp_add_address_format_replacement($replacements, $data)
{
    // 因為在這裡只加入帳單(billing)的手機號碼欄位,沒有運送(shipping)的手機欄位
    // 而透過woocommerce_localisation_address_formats修改格式的話沒有辦法去區別是billing還是shipping
    // 且上一步octopuswp_add_order_address_data只加入billing的資料
    // 所以在這裡就要判斷是否有這個資料存在
    $replacements['{mobile_number}'] = !empty($data['mobile_number']) ? $data['mobile_number'] : '';
    return $replacements;
}

效果如下:

第二種是直接修改WC_Order::get_formatted_billing_address產出的html,透過woocommerce_order_get_formatted_billing_address這個filter hook

add_filter('woocommerce_order_get_formatted_billing_address', 'octopuswp_add_mobile_number_to_formatted_address_html', 10, 3);
/**
 * 將自訂欄位資料加入到formatted address的html
 * @param string $formatted_address_html
 * @param array $address_data
 * @param WC_Order $order
 * @return string
 */
function octopuswp_add_mobile_number_to_formatted_address_html($formatted_address_html, $address_data, $order)
{
    $formatted_address_html .= $order->get_meta('_billing_mobile_number');
    return $formatted_address_html;
}

 

3. 將自訂的結帳欄位顯示在後台

後台訂單頁面,預設有個區塊是拿來顯示結帳欄位資訊的

可以使用woocommerce_admin_billing_fieldswoocommerce_admin_shipping_fields來將自訂的欄位加進去

add_filter('woocommerce_admin_billing_fields', 'octopuswp_add_admin_billing_fields');
/**
 * 加入自訂欄位資料到後台定單頁面
 * @param array $fields
 */
function octopuswp_add_admin_billing_fields($fields)
{
    // 這裡的key -> mobile_number,會讓woocommerce自己去抓取結帳欄位key為billing_mobile_number的資料
    // 所以只要填入mobile_number就好,不用填入完整的billing_mobile_number
    $fields['mobile_number'] = [
        'label' => '手機號碼', // 欄位標籤
        'show' => true //再沒有按下編輯按鈕時,是否顯示出來,預設為true
    ];
    return $fields;
}

這裡的欄位參數也提供了type、options、class可填,type預設為text


延伸閱讀:


此篇文章版權屬於OctopusWP

轉載請註明出處 @OctopusWP (https://www.octopuswp.com)

發佈留言

×

Cart