Save selected country from countries dropdown in WooCommerce registration

55 Views Asked by At

I'm struggling with my custom registration fields for WooCommerce. I need 2 registration fields.

  1. B2B
  2. B2C

So I was thinking to create two registration pages, one for B2B and one for B2C.

I created the pages, added the code and registered the new fields in the database. This works all fine, but not for 1 field. It's a dropdown field for choosing the country.

The code below is a normal input. This field is registered in the database at registration and de value is added to the WooCommerce account page from the registered user.

<div class="col-md-12">
    <label for="reg_billing_city"><?php _e( 'City', 'woocommerce' ); ?><span class="required">*</span></label>
    <input type="text" class="input-text" name="billing_city" id="reg_billing_city" value="<?php if ( ! empty( $_POST['billing_city'] ) ) esc_attr_e( $_POST['billing_city'] ); ?>" />
</div>

I also need the country of the registered user at the account page. I'm using the code below:

<div class="col-md-12">
    <label for="reg_billing_country"><?php _e( 'Country', 'woocommerce' ); ?><span class="required">*</span></label>
    <select class="input-text" name="billing_country" id="reg_billing_country" value="<?php if ( ! empty( $_POST['billing_country'] ) ) esc_attr_e( $_POST['billing_country'] ); ?>">
        <option value="Nederland">Nederland</option>
        <option value="Belgie">Belgie</option>
        <option value="Duitsland">Duitsland</option>
        <option value="Frankrijk">Frankrijk</option>
    </select>
</div>

But the value from billing_country is not added to the customs account page.

if ( isset( $_POST['billing_country'] ) ) {
    update_user_meta( $customer_id, 'billing_country', sanitize_text_field( $_POST['billing_country'] ) );
}

So how to get the value of the dropdown updated to the user metadata?

1

There are 1 best solutions below

0
LoicTheAztec On

There are some mistakes in your code for the billing country field:

  1. you need to set the country code as <option value="{$country_code}">.
  2. There is no value="" in the <select> itself, instead you need to set for the corresponding selected option value, the attribute selected.

Here is the complete code, displaying the fields, validating and saving:

add_filter( 'woocommerce_register_form', 'additional_registration_fields' );
function additional_registration_fields() {
    $countries = WC()->countries->get_countries(); // Get countries array (code / label name pairs)
    $selected  = isset($_POST['billing_country']) ? esc_attr($_POST['billing_country']) : '';
    ?>
    <div class="col-md-12 form-row form-row-wide">
        <label for="reg_billing_country"><?php _e( 'Country', 'woocommerce' ); ?> <span class="required">*</span></label>
        <select class="country_select input-text" name="billing_country" id="reg_billing_country"><?php 
            printf('<option value="" %s> %s</option>', selected('', $selected, false), __('Select your country','woocommerce') );
            
            foreach ( array('NE','BE','DE','FR') as $key ) :
                printf('<option value="%s" %s>%s</option>', $key, selected($key, $selected, false), $countries[$key] );
            endforeach; 
            ?>
        </select>
    </div>
    <?php
    $billing_city = isset($_POST['billing_country']) ? sanitize_text_field($_POST['billing_country']) : '';
    ?>
    <div class="col-md-12 form-row form-row-wide">
        <label for="reg_billing_city"><?php _e( 'City', 'woocommerce' ); ?><span class="required">*</span></label>
        <input type="text" class="input-text" name="billing_city" id="reg_billing_city" value="<?php echo $billing_city; ?>" />
    </div>
    <?php
}

// Validate WooCommerce registration form custom fields.
add_action( 'woocommerce_register_post', 'wc_validate_reg_form_fields', 10, 3 );
function wc_validate_reg_form_fields($username, $email, $validation_errors) {
    if (isset($_POST['billing_country']) && empty($_POST['billing_country']) ) {
        $validation_errors->add('billing_country_error', __('Country is a required field.', 'woocommerce'));
    }
    if (isset($_POST['billing_city']) && empty($_POST['billing_city']) ) {
        $validation_errors->add('billing_city_error', __('City is a required field.', 'woocommerce'));
    }
    return $validation_errors;
}

// Save WooCommerce registration custom fields values.
add_action( 'woocommerce_created_customer', 'wc_save_registration_form_fields' );
function wc_save_registration_form_fields( $customer_id ) {
    if ( isset($_POST['billing_country']) && ! empty($_POST['billing_country']) ) {
        update_user_meta( $customer_id, 'billing_country', esc_attr($_POST['billing_country']) );
    }
    if ( isset($_POST['billing_city']) && ! empty($_POST['billing_city']) ) {
        update_user_meta( $customer_id, 'billing_city', sanitize_text_field($_POST['billing_city']) );
    }
}

Code goes in functions.php file of your child theme (or in a plugin). It should work.


Addition

Add "Account type" dropdown to registration form start

Instead of using 2 registration forms, you could add a dropdown for the "Account type" in the registration form start, like:

add_filter( 'woocommerce_register_form_start', 'account_type_registration_field' );
function account_type_registration_field() {
    $countries = WC()->countries->get_countries(); // Get countries array (code / label name pairs)
    $selected  = isset($_POST['account_type']) ? esc_attr($_POST['account_type']) : '';
    ?>
    <div class="col-md-12 form-row form-row-wide">
        <label for="reg_account_type"><?php _e( 'Account type', 'woocommerce' ); ?> <span class="required">*</span></label>
        <select class="account_select input-text" name="account_type" id="reg_account_type"><?php 
            printf('<option value="" %s> %s</option>', selected('', $selected, false), __('Select your account type','woocommerce') );
            printf('<option value="customer" %s>%s</option>', selected('customer', $selected, false), __('Customer','woocommerce') );
            printf('<option value="wholesale" %s>%s</option>', selected('wholesale', $selected, false), __('Wholesale','woocommerce') );
            ?>
        </select>
    </div>
    <?php
}

Then you will add into the validation function:

if (isset($_POST['account_type']) && empty($_POST['account_type']) ) {
    $validation_errors->add('account_type_error', __('Account type a required field.', 'woocommerce'));
}

And in the saving function:

if (isset($_POST['account_type']) && ! empty($_POST['account_type']) ) {
    update_user_meta( $customer_id, 'account_type', esc_attr($_POST['account_type']) );
}

To finish, if you need to show / hide some fields depending on the selected account type value, you can use JavaScript / jQuery…