【问题标题】:Show/hide shipping methods based on a WooCommerce checkout field value根据 WooCommerce 结帐字段值显示/隐藏运输方式
【发布时间】:2021-11-22 05:15:00
【问题描述】:

在 WooCommerce 中,我设置了不同的运输方式但必须特别为公司提供一种。

为此,我使用以下代码:

add_filter( 'woocommerce_package_rates', array( $this, 'package_rates' ), 10, 2 );

public function package_rates( $rates, $package ) {
    $company_rate_id = 'flat_rate:7';

    if(!empty(WC()->customer->get_billing_company())){
        $company_rates = $rates[ $company_rate_id ];
        $rates = array( $company_rate_id => $company_rates );
    }else{
        unset( $rates[ $company_rate_id ] );
    }

    return $rates;
}

该解决方案有效,但前提是计费公司已经存在并保存在数据库中。因此,如果客户在结帐页面上更新此信息,它就不起作用了。

可能的解决方案是实时保存该字段(billing_company)。

我尝试了以下功能:

add_filter( 'woocommerce_checkout_fields' , 'trigger_update_checkout_on_change' );
function trigger_update_checkout_on_change( $fields ) {

    $fields['billing']['billing_company']['class'][] = 'update_totals_on_change';

    return $fields;
}

这更新了运输方式,问题又是,该字段没有保存在数据库中,package_rates()函数无法实时找到它。

【问题讨论】:

    标签: php jquery ajax woocommerce checkout


    【解决方案1】:

    这比那要复杂一些……需要 jQuery 和 Ajax 代码才能根据结帐字段用户输入显示/隐藏运输方式。

    以下代码将启用根据结帐公司字段显示/隐藏预定义的运输方式:

    // Conditionally show/hide shipping methods
    add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 );
    function shipping_package_rates_filter_callback( $rates, $package ) {
        // The defined rate id
        $company_rate_id = 'flat_rate:7';
    
        if( WC()->session->get('company' ) === '1' ) {
            $rates = array( $company_rate_id => $rates[ $company_rate_id ] );
        } else {
            unset( $rates[ $company_rate_id ] );
        }
        return $rates;
    }
    
    // function that gets the Ajax data
    add_action( 'wp_ajax_get_customer_company', 'wc_get_customer_company' );
    add_action( 'wp_ajax_nopriv_get_customer_company', 'wc_get_customer_company' );
    function wc_get_customer_company() {
        if ( isset($_POST['company']) && ! empty($_POST['company']) ){
            WC()->session->set('company', '1' );
        } else {
            WC()->session->set('company', '0' );
        }
        die(); // (required)
    }
    
    // The Jquery Ajax script
    add_action( 'wp_footer', 'custom_checkout_script' );
    function custom_checkout_script() {
        if( WC()->session->__isset('company') ) 
            WC()->session->__unset('company');
    
        // Only on checkout when billing company is not defined
        if( is_checkout() && ! is_wc_endpoint_url() ):
        ?>
        <script type="text/javascript">
        jQuery( function($){
            if (typeof wc_checkout_params === 'undefined') 
                return false;
    
            var fieldId = 'input#billing_company';
    
            function companyTriggerAjax( company ){
                $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action': 'get_customer_company',
                        'company': company,
                    },
                    success: function (result) {
                        // Trigger refresh checkout
                        $('body').trigger('update_checkout');
                    }
                });
            }
    
            // On start
            if( $(fieldId).val() != '' ) {
                companyTriggerAjax( $(fieldId).val() );
            }
    
            // On change
            $(fieldId).change( function () {
                companyTriggerAjax( $(this).val() );
            });
        });
        </script>
        <?php
        endif;
    }
    
    // Enabling, disabling and refreshing session shipping methods data
    add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
    function refresh_shipping_methods( $post_data ){
        $bool = true;
    
        if ( WC()->session->get('company' ) === '1' )
            $bool = false;
    
        // Mandatory to make it work with shipping methods
        foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
            WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
        }
        WC()->cart->calculate_shipping();
    }
    

    代码进入您的活动子主题(或活动主题)的 function.php 文件中。经过测试并且可以工作。


    相关:Remove shipping cost if custom checkbox is checked in WooCommerce Checkout

    【讨论】:

    • 有一个小问题,假设您已经在 billing 字段中存储了信息。如果您到达结帐处,删除该字段的内容并刷新页面(或导航到另一个部分),返回结帐时,帐单字段将显示已保存的内容,并且货件将显示为没有公司。反之亦然,如果没有保存公司,填写公司,导航返回,就会出现公司的发货。谢谢你的一切
    • @RafaelCalero 我已经更新了答案......它将处理您描述的情况,如果重新加载结帐页面,则从会话中删除数据。如果这个答案回答了你的问题,你可以请accept回答,谢谢。
    • 提前,再次感谢。这解决了它最初为空的情况。但公司最初挽救的案例仍然失败。
    • 你是对的!我一直在全新安装中进行测试,您的解决方案可以正常工作。它必须与之前的一些发展相冲突。谢谢你的一切
    猜你喜欢
    • 2018-03-19
    • 1970-01-01
    • 2019-07-22
    • 2021-06-24
    • 2020-10-03
    • 1970-01-01
    • 2014-07-05
    • 2020-12-12
    相关资源
    最近更新 更多