在WooCommerce加入客製化使用者欄位

前言

由於業主有增加WooCommerce客製化使用者欄位的需求,所以這篇文章想分享一些客製化使用者欄位經歷。因為預期會有許多後續寄送收據、報帳與聯絡需要,業主想在使用者註冊時就先填好資料,或者使用社群網站 (Facebook or Google) 一鍵登入後能繼續填寫客製化欄位,所以在註冊表單、編輯個人帳號、購物車結帳前,後台查詢訂單這四處要加上客制化欄位。

搜尋參考資料有找到一位WooCommerce plugin開發者寫的詳細教學文章,英文文件但值得一看,以下參考他的文章增加業主所需的客製欄位。code的部分要打包成外掛Plugin或者是MU Plugin (Must Use Plugin)都可以。

在WooCommerce加入客製化使用者欄位

定義客製化欄位

要加入客製化欄位得先知道要放哪些欄位、類別跟必塡/選填,所以得先定義這些欄位。

'first_name' => array(
	'type' => 'text',
	'label' => __('First Name', 'iconic') ,
	'hide_in_account' => true,
	'hide_in_admin' => true,
	'hide_in_checkout' => true,
	'hide_in_registration' => false,
	'required' => true,
) , 
'embraced-status' => array(
	'type' => 'select',
	'label' => __('身份 Status', 'iconic') ,
	'options' => array(
		'' => __('身份 Status', 'iconic') ,
		1 => __('社會人士 Member of society', 'iconic') ,
		2 => __('學生 Student', 'iconic') ,
		3 => __('團體 Group', 'iconic') ,
	) ,
	'required' => true,
) , 
'embraced-type' => array(
	'type' => 'select',
	'label' => __('類別 Type', 'iconic') ,
	'options' => array(
		'' => __('類別 Type', 'iconic') ,
		1 => __('工商業 Industrial or business marketing', 'iconic') ,
		2 => __('研究機構 Research institue', 'iconic') ,
		3 => __('學術 Academia', 'iconic') ,
		4 => __('其他 Other', 'iconic') ,
	) ,
	'required' => true,
) ,

 

這邊的例子是建立名字(文字欄位),身份與類別兩個下拉式選單:
type是欄位類別可以選:

  • Text 文字
  • Textarea 文字區塊
  • Select 下拉式選單
  • Country 國家
  • Checkbox 單勾選
  • Number 數字
  • Password 密碼
  • Email
  • Tel 電話

原文教學內還有教怎麼做單選的radio button與多勾選。

掛上欄位

定義好欄位,使用原文的驗證與更新functions,掛到對應的action hooks:’woocommerce_register_form’, ‘woocommerce_edit_account_form’,如名稱,分別是掛到註冊表單與個人資訊表單就可以用了。

add_action('woocommerce_register_form', 'iconic_print_user_frontend_fields', 10); // 註冊表單 register form of WooCommerce
add_action('woocommerce_edit_account_form', 'iconic_print_user_frontend_fields', 10); // 個人資訊 my account section of WooCommerce

 

更新驗證表單資料 & 訂單成立後更新資料

驗證與更新這邊沒有修改內容就不多說,倒是訂單結帳前也有欄位要填,所以在訂單成立之後得更新資料,因為原本的儲存function是以user為主,所以我另外改了一個以訂單為輸入的function,把資訊填在user/order的meta data,其實寫在user的metadata就好了,只是想說後台是讀取訂單資訊就寫在訂單內了,可以少一次query (誤)。

function iconic_save_account_fields2($order, $data){
	$customer_id = $order->get_user_id();
	$fields = iconic_get_account_fields();
	$sanitized_data = array();
	foreach($fields as $key => $field_args) {
		if (!iconic_is_field_visible($field_args)) {
			continue;
		}

		$sanitize = isset($field_args['sanitize']) ? $field_args['sanitize'] : 'wc_clean';
		$value = isset($data[$key]) ? call_user_func($sanitize, $data[$key]) : ''; // 客製化欄位的key前面要有一個底線 _,例如原本定義的key是firstname,就是_firstname,視為private。
		$meta_key = '_' . $key;
		if (iconic_is_userdata($key)) {
			$sanitized_data[$key] = $value;
			continue;
		}

		update_user_meta($customer_id, $key, $value);
		$order->update_meta_data($meta_key, $value);
	}

	if (!empty($sanitized_data)) {
		$sanitized_data['ID'] = $customer_id;
		wp_update_user($sanitized_data);
	}
}

function apply_username_field(){
	if (is_user_logged_in()) {
		$current_user = wp_get_current_user();
		$user_id = $current_user->ID;
		$fields = iconic_get_account_fields();
		$cname = get_user_meta($user_id, 'embraced-CName');
		$ename = get_user_meta($user_id, 'embraced-EngName');
		$company = get_user_meta($user_id, 'embraced-organization') [0];
		if (!empty($cname[0])) { //依照中文名 -> 英文名 -> User內的first name順序
			$firstname = $cname[0];
		}
		else if (!empty($ename[0])) {
			$firstname = $ename[0];
		}
		else {
			$firstname = $current_user->user_firstname;
		}

		$output = '
      <script>
        var $ = jQuery.noConflict();
        $(document).ready(function(){
        $("#billing_first_name").attr("value","' . $firstname . '");
        $("#billing_company").attr("value","' . $company . '");
        })
      </script>';
		echo $output;
	}
}

add_filter('woocommerce_before_checkout_form', 'apply_username_field', 30);

 

以First Name欄位替代First Name + Last Name欄位

這個部分忘記是參考哪位前輩寫的文章,總之是簡化姓名欄位為一個。

//remove default billing fields
function custom_override_checkout_fields( $fields ) {
     //unset($fields['billing']['billing_first_name']); 保留帳單的first_name替代first name & last Name
     unset($fields['billing']['billing_last_name']);
     unset($fields['billing']['billing_country']);
     //unset($fields['billing']['billing_company']); 保留帳單的公司欄位
     unset($fields['billing']['billing_address_1']);
     unset($fields['billing']['billing_address_2']);
     unset($fields['billing']['billing_city']);
     unset($fields['billing']['billing_postcode']);
     unset($fields['billing']['billing_state']);
     unset($fields['billing']['billing_phone']);
     //use first name to fill full name
     $fields['billing']['billing_first_name'] = array(
         'label'=>"姓名",
         'required' => true,
     );

     return $fields;
}

function my_custom_checkout_field_display_admin_order_meta($order){
    $fields = iconic_get_account_fields();
		$order_id = $order->get_id();
    foreach ($fields as $key => $field_args){
      if ($field_args['type'] === 'select'){
        echo '<p><strong>'.$field_args['label'].':</strong> ' . $field_args['options'][get_post_meta( $order_id, '_'.$key, true )] . '</p>';
      }else{
        echo '<p><strong>'.$field_args['label'].':</strong> ' . get_post_meta( $order_id, '_'.$key, true ) . '</p>';
      }
    }
}

add_filter('woocommerce_checkout_fields', 'custom_override_checkout_fields', 10, 1); // 以客製欄位替代帳單欄位
add_filter('woocommerce_checkout_fields', 'iconic_checkout_fields', 20, 1); // 結帳的客製化表單
add_action('woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1); // 後台訂單

 

結論

照著開頭那篇文章可以好好的客製化需要的欄位,搭配WooCommerce文件與討論,就可以完成此客製化功能。
大概會像這樣:

[ux_slider]

[ux_image id=”311″ image_size=”medium” width=”30″]

[ux_image id=”309″ image_size=”medium” width=”50″]

[ux_image id=”341″ image_size=”medium” width=”50″]

[/ux_slider]

相關文章