[WooCommerce] 根據選擇運送方式修改結帳欄位的方法

本篇文章更新時間:2019/09/04
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣新台幣 贊助支持。


一直以為自己筆記過,但後來想想應該是根據金流而已,新需求就來寫!

寫到這邊就會想到綠界物流外掛的痛! 到底他是金流還是物流?這個決定可是會影響很多邏輯。始終沒有一個版本的外掛是套上去就真的可以不用改啥來配合了。(不過我也相信這是無解的問題)

本文需求明確的說是:選到了 A 運送方式,結帳欄位不該出現 X 項目,所以想拿掉/修改/新增怎辦?

舉例:自取的時候,還要人填寫地址是不是怪怪的?

首先,要實作這塊的邏輯也一定是從結帳表單方法下手。([WooCommerce] 調整結帳欄位的終極指南

把結帳欄位的 hook 方法中補上判斷式,判別當前選擇的運送方式來決定是否開啟或關閉欄位項目。

function mxp_checkout_fields_modify_base_on_shipping_method($fields) {
    //讀取當前選擇的運送方式方法
    $chosen_methods = WC()->session->get('chosen_shipping_methods');
    //因為取得的是某個方法,而不是某種方法,所以要拆解一下。我知道這邊有點難懂,請搭配下文補充
    $chosen_shipping = current(explode(':', $chosen_methods[0]));
    //判斷是否符合自取條件
    if ($chosen_shipping == 'local_pickup') {
        //使用覆寫的方式,不是重新建立,重新建立反而可能會有其他問題!
        $fields['billing']['billing_postcode']['required'] = false;
        $fields['billing']['billing_postcode']['class'] = array('hidden');
        $fields['billing']['billing_postcode']['type'] = 'hidden';
        $fields['billing']['billing_address_1']['required'] = false;
        $fields['billing']['billing_address_1']['class'] = array('hidden');
        $fields['billing']['billing_address_1']['type'] = 'hidden';
        $fields['billing']['billing_state']['required'] = false;
        $fields['billing']['billing_state']['class'] = array('hidden');
        $fields['billing']['billing_state']['type'] = 'hidden';
        $fields['billing']['billing_city']['required'] = false;
        $fields['billing']['billing_city']['class'] = array('hidden');
        $fields['billing']['billing_city']['type'] = 'hidden';
    }
    return $fields;
}

add_filter('woocommerce_checkout_fields', 'mxp_checkout_fields_modify_base_on_shipping_method', 999, 1);

關於註解提到的那方法讀取到的是「某個運送方法」而不是「某種運送方法」這件事,雖沒特別在 [WooCommerce] 運送方法項目的排序控制(依照運費、指定順序) 這篇提到,但算是滿重要的觀念!

WooCommerce 的運送方式可以設定的很細,出發點是一個集合概念,還可以從這個集合下去延伸個別的子項目,所以會這樣形容。

像「宅配」是一個運送方式種類,但「海外宅配」跟「國內宅配」就是不同的子集合了!只針對「宅配」去實作可能會不夠彈性,導致影響其他設定的操作。

到這邊這題只解一半。從購物車頁選好運送方式過去結帳頁面的人會正常,但如果是結帳頁面反悔要改選運送方式的人就會感覺奇怪了。

這時候會需要使用 [WooCommerce] 片段(fragments)互動程式設計要點 這篇提到的開發方法來補強了!

更改運送方式的時候會觸發 woocommerce_update_order_review_fragments 的 hook ,在這邊去判斷當前選擇運送方式來處理輸出更新的欄位替換。

function mxp_hidden_checkout_fields_base_on_shipping_method($value) {
    // 判斷當前選擇到的運送方式
    $chosen_methods = WC()->session->get('chosen_shipping_methods');
    $chosen_shipping = current(explode(':', $chosen_methods[0]));
    if ($chosen_shipping == 'local_pickup') {
        $fields = WC()->checkout->get_checkout_fields('billing');
        $html = "";
        foreach ($fields as $key => $field) {
            $field['return'] = true;
            // 判斷對應需要調整的欄位來改參數重新產生欄位結構輸出
            if ($key == 'billing_postcode' || $key == 'billing_address_1' || $key == 'billing_state' || $key == 'billing_city') {
                $field['class'] = array('hidden');
                $field['type'] = 'hidden';
                $field['required'] = false;
            }
            $html .= woocommerce_form_field($key, $field, WC()->checkout->get_value($key));
        }
        $value['.woocommerce-billing-fields__field-wrapper'] = '
' . $html . '
'; } else { // 不符合條件的就照常輸出 $fields = WC()->checkout->get_checkout_fields('billing'); $html = ""; foreach ($fields as $key => $field) { $field['return'] = true; $html .= woocommerce_form_field($key, $field, WC()->checkout->get_value($key)); } $value['.woocommerce-billing-fields__field-wrapper'] = '
' . $html . '
'; } return $value; } add_filter('woocommerce_update_order_review_fragments', 'mxp_hidden_checkout_fields_base_on_shipping_method', 999, 1);

Gist: Link

到這邊就能滿足本命題最預設情境的條件拉! 打完收工~


Share:

作者: Chun

資訊愛好人士。主張「人人都該為了偷懶而進步」。期許自己成為斜槓到變進度條 100% 的年輕人。[///////////____36%_________]

參與討論

  1. simengli
  2. Chun
  3. lamqscv
  4. trista_tien
  5. sdf1597530
  6. a0928315654

15 則留言

  1. 你好
    请问一下我现在做一个网站,想在客人选择送货的情况下到达一定金额有礼物送,但是自取就没有,我找了一些插件但是都不能单独设定送货,请问有什么办法吗?谢谢

    1. Hi! 你的需求看起來就是只能客製化來開發了,應用本篇的程式邏輯,改寫成「當選到某些送貨條件」且「購物車滿足一定金額」就觸發,沒有就是移除購物車的禮物或是折扣。這塊還可以搭配我這篇參考: https://www.mxp.tw/8300/

  2. 你好,先要感謝你,因為這功能真的很實用
    但我使用時發現我結帳頁面另一邊用 WC()->cart->shipping_total 的部分會掛掉
    原先是即時按運輸方式顯示運費,現在就變成不停轉圈,運費也不能讀取
    有什麼建議的解決方式嗎?

    1. 可能有哪裡執行上衝突,可否調閱出那段時間操作下PHP顯示的錯誤訊息?有助於調查問題。

      這可能要到主機端裡找,不在WordPress內建的相關訊息裡。(或嘗試使用Error log相關的外掛輔助看看)

      1. 不太能找到相關外掛
        大多都沒顯示error
        主機端是指debug.log嗎

        1. 「主機端」是指主機內伺服器 php_error.log 記錄錯誤執行的檔案哦!

  3. 您好,因為運送選項不是自取,而是超商7-11和全家,要填寫地址也怪怪的。那麼:
    //判斷是否符合自取條件
    if ($chosen_shipping == ‘local_pickup’) {
    以上的local_pickup是需要做更換嗎?若要做更換,是要更換成什麼呢?

    1. 需要更換哦!這邊要更換成你使用超取外掛內定義的「關鍵字」,讓程式邏輯能夠判斷。至於你用哪套,是什麼「關鍵字」我就不知道了!

  4. 謝謝大大!替換成 ecpay_shipping 就可以拿來作為綠界超取的設定
    大大太強啦~~~~~!

  5. 感謝大大分享
    但是用到我的站之後,有一個奇怪的狀況是
    如果一開始地址的欄位沒填東西
    儘管程式碼成功讓地址為非必填
    要前往付款的時候,系統還是會說地址為必填
    導致沒辦法下單QQ

    1. 針對你這問題,我寫了一篇新文章:[WooCommerce] 結帳頁面設定欄位必填、非必填、隱藏或是移除欄位的方法
      https://www.mxp.tw/9191/

      試試看比對來改囉~

  6. 首先,謝謝大大的教學。

    小弟不精,想請教。
    我使用後,想把else內的改成我想要顯的欄位,並且有下拉功能,我該如何用?

    1. 看不是很懂你的需求。這邊寫的程式都是背後運作來令 WooCommerce 自動更新時做調整的影響,不會有前端視覺上操作的改變。

  7. 感謝提供的方法,非常實用!
    然而,如果要將運送到不同的地址? 這個核取方塊也取消,我可以從哪方面著手。
    不知為何Woocommerce在自行取貨時,為何要留下地點和這個核取方塊。

    1. 那個 checkbox 可以用
      1. (子)主題覆蓋改寫 woocommerce/checkout/form-shipping.php
      2. 設定不需要運送 WC()->cart->needs_shipping_address()
      3. CSS #ship-to-different-address 隱藏

      其實這選項只是純粹算預留,也給了很多彈性來讓你改寫。參考看看囉~

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


文章
Filter
Apply Filters
Mastodon