根据发货国家/地区将 Woocommerce 结帐电话字段设为可选

Posted

技术标签:

【中文标题】根据发货国家/地区将 Woocommerce 结帐电话字段设为可选【英文标题】:Make Woocommerce checkout phone field optional based on shipping country 【发布时间】:2019-08-07 22:53:55 【问题描述】:

在 Woocommerce 结帐中,我正在尝试使特定发货国家/地区不需要电话字段。基于 "Make checkout phone field optional for specific countries in WooCommerce" 答案代码,它工作正常,我尝试进行一些更改以使此代码适用于 shipping 国家而不是 billing 国家。

经过多次尝试,我无法弄清楚如何让它发挥作用。

任何帮助都会很棒,非常感谢。

【问题讨论】:

【参考方案1】:

非常感谢@LoicTheAztec 的原始答案,但是该解决方案现在给出了不稳定的结果,只是在必需和可选状态(开/关)之间交替切换电话字段。

最初的答案也没有考虑到只使用账单地址并且没有输入单独的送货地址或送货地址的客户。

请查看以下 2019 年的更新版本

// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field()
    return array( 'GB', 'JE', 'GG', 'IM' );


// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) 

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Get Customer shipping country
    $shipping_country = WC()->customer->get_shipping_country();

    // Only on checkout page and My account > Edit address for billing phone field
    if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
    && in_array($shipping_country, $countries) ) || is_checkout() ) ) 
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    
    return $field;


// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) 

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Get Customer shipping country
    $shipping_country = WC()->customer->get_shipping_country();

    // Only on checkout page and My account > Edit address
    if ( ( is_wc_endpoint_url( 'edit-address' )
    && in_array($shipping_country, $countries) ) || is_checkout() )
        $fields['billing_phone']['required'] = false;

    return $fields;


// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) 
    $required = esc_attr__( 'required', 'woocommerce' );

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Hidden field for the phone number validation
    echo '<input type="hidden"  name="billing_phone_check" id="billing_phone_check" value="0">';
    $countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
    ?>
    <script type="text/javascript">
        (function($)
            var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>';
            var countries = [<?php echo $countries_str; ?>];
                if($('.shipping_address').is(':visible')) 
                    // ship to different country selected
                    var selectedcountry = $('#shipping_country option:selected').val();
                 else 
                    var selectedcountry = $('#billing_country option:selected').val();
                
             //var selectedcountry = $('#shipping_country option:selected').val();
             var phoneCheck = 'input#billing_phone_check';
             var phoneField = '#billing_phone_field';

            function actionRequire( actionToDo='yes', selector='' )
                if ( actionToDo == 'yes' ) 
                    $(selector).addClass("validate-required");
                    $(selector+' label > .required').remove();
                    $(selector+' label').append(required);
                 else 
                    $(selector).removeClass("validate-required");
                    $(selector+' label > .required').remove();
                
                $(selector).removeClass("woocommerce-validated");
                $(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
            

            // Default value Once DOM is loaded (with a 300 ms delay)
            setTimeout( function()
                if($('.shipping_address').is(':visible')) 
                    // ship to different country selected
                    var selectedcountry = $('#shipping_country option:selected').val();
                 else 
                    var selectedcountry = $('#billing_country option:selected').val();
                
                actionRequire( 'no', phoneField );
                if( $.inArray( selectedcountry, countries ) == -1)
                    actionRequire( 'yes',phoneField );
                    $(phoneCheck).val('1');
                
            , 300 );

            // Live value
            $( 'form.checkout' ).on( 'change', '#billing_country, #shipping_country, #ship-to-different-address-checkbox', function()
                setTimeout( function()
                    if($('.shipping_address').is(':visible')) 
                        // ship to different country selected
                        var selectedcountry = $('#shipping_country option:selected').val();
                     else 
                        var selectedcountry = $('#billing_country option:selected').val();
                    

                    if ( $.inArray( selectedcountry, countries ) == -1) 
                        actionRequire( 'yes' ,phoneField );
                        $(phoneCheck).val('1');
                     else 
                        actionRequire( 'no' ,phoneField );
                        $(phoneCheck).val('0');
                    
                , 300 );
            );
       )(jQuery);
        </script>
    <?php


// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() 
    // Check if set, if its not set add an error.
    if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
        wc_add_notice( __( 'Please enter a number phone.' ), 'error' );

【讨论】:

【参考方案2】:

以下代码将使计费电话字段仅适用于特定的“送货”国家/地区。

自 Woocommerce 3.4+ 版以来,Woocommerce 表单字段发生了一些变化,因此需要额外的功能和代码。

我还扩展了代码以处理“我的帐户”>“编辑地址”中的电话字段行为,客户可以在其中更改其帐户数据。

这是完整的代码(在第一个函数中定义你的国家代码)

// SETTINGS: The countries codes (2 capital letters) in the array
function defined_countries_for_phone_field()
    return array( 'UK', 'BE', 'GE', 'IT', 'ES' );


// Remove "(optional)" from non required "Billing phone" field
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) 

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Get Customer shipping country
    $shipping_country = WC()->customer->get_shipping_country();

    // Only on checkout page and My account > Edit address for billing phone field
    if( 'billing_phone' === $key && ( ( is_wc_endpoint_url( 'edit-address' )
    && ! in_array($shipping_country, $countries) ) || is_checkout() ) ) 
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    
    return $field;


// Make the billing phone field optional (by default)
add_filter( 'woocommerce_billing_fields', 'filter_billing_phone_field', 10, 1 );
function filter_billing_phone_field( $fields ) 

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Get Customer shipping country
    $shipping_country = WC()->customer->get_shipping_country();

    // Only on checkout page and My account > Edit address
    if ( ( is_wc_endpoint_url( 'edit-address' )
    && ! in_array($shipping_country, $countries) ) || is_checkout() )
        $fields['billing_phone']['required'] = false;

    return $fields;


// Real time shipping country selection actions
add_action( 'woocommerce_after_order_notes', 'custom_checkout_scripts_and_fields', 10, 1 );
function custom_checkout_scripts_and_fields( $checkout ) 
    $required = esc_attr__( 'required', 'woocommerce' );

    // Get the defined countries codes
    $countries = defined_countries_for_phone_field();

    // Hidden field for the phone number validation
    echo '<input type="hidden"  name="billing_phone_check" id="billing_phone_check" value="0">';
    $countries_str = "'".implode( "', '", $countries )."'"; // Formatting countries for jQuery
    ?>
    <script type="text/javascript">
        (function($)
            var required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>',
                countries = [<?php echo $countries_str; ?>],
                location = $('#shipping_country option:selected').val(),
                phoneCheck = 'input#billing_phone_check',
                phoneField = '#billing_phone_field';

            function actionRequire( actionToDo='yes', selector='' )
                if ( actionToDo == 'yes' ) 
                    $(selector).addClass("validate-required");
                    $(selector+' label').append(required);
                 else 
                    $(selector).removeClass("validate-required");
                    $(selector+' label > .required').remove();
                
                $(selector).removeClass("woocommerce-validated");
                $(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
            

            // Default value Once DOM is loaded (with a 300 ms delay)
            setTimeout( function()
                actionRequire( 'no', phoneField );
                if( $.inArray( location, countries ) >= 0  && $(phoneCheck).val() == '0' )
                    actionRequire( 'yes',phoneField );
                    $(phoneCheck).val('1');
                
            , 300 );

            // Live value
            $( 'form.checkout' ).on( 'change', '#shipping_country', function()
                var location = $('#shipping_country option:selected').val();
                if ( $.inArray( location, countries ) >= 0 && $(phoneCheck).val() == 0 ) 
                    actionRequire( 'yes' ,phoneField );
                    $(phoneCheck).val('1');
                 else if ( $(phoneCheck).val() == 1 ) 
                    actionRequire( 'no' ,phoneField );
                    $(phoneCheck).val('0');
                
            );
       )(jQuery);
        </script>
    <?php


// Phone number validation, when the field is required
add_action('woocommerce_checkout_process', 'billing_phone_field_process');
function billing_phone_field_process() 
    // Check if set, if its not set add an error.
    if ( ! $_POST['billing_phone'] && $_POST['billing_phone_check'] == '1' )
        wc_add_notice( __( 'Please enter a number phone.' ), 'error' );

代码进入您的活动子主题(或活动主题)的 function.php 文件中。已在 WooCommerce 3.4 及更高版本中测试并运行。

相关:

Make checkout phone field optional for specific countries in WooCommerce Remove "(optional)" text from checkout fields in Woocommerce 3.4+

【讨论】:

现在给出不稳定的结果,不确定 WooCommerce 中是否发生了一些会发生冲突的变化,但请查看我的答案以获取更新版本

以上是关于根据发货国家/地区将 Woocommerce 结帐电话字段设为可选的主要内容,如果未能解决你的问题,请参考以下文章

在 Woocommerce 中将结帐国家/地区下拉列表设为只读

如何在 WooCommerce 中更改结帐国家/地区选择的悬停颜色?

根据支付网关和国家/地区对 WooCommerce 自定义费用征税

php [WooCommerce Core]更改结帐时的默认状态和国家/地区

php [WooCommerce Core]更改结帐时的默认状态和国家/地区

根据 WooCommerce 中的运输类别自定义计算的运输成本