在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_fields
及woocommerce_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