How to save WooCommerce checkout custom fields to user meta

Steve picture Steve · Apr 19, 2016 · Viewed 10.9k times · Source

I've created the following custom fields for the user meta using the PODS.io Wordpress plugin:

  • date_of_birth
  • emergency_contact_name
  • relation
  • emergency_phone

I've added these fields to the WooCommerce checkout, under extra information, by using the following code in my theme's functions.php:

add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );

function my_custom_checkout_field( $checkout ) {

    woocommerce_form_field( 'date_of_birth', array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Date of Birth'),
        'placeholder'   => __('dd/mm/yyyy'),
        ), $checkout->get_value( 'date_of_birth' ));

    woocommerce_form_field( 'emergency_contact_name', array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Emergency Contact Name'),
        'placeholder'   => __('contact name'),
        ), $checkout->get_value( 'emergency_contact_name' ));

    woocommerce_form_field( 'relation', array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Emergency Relation'),
        'placeholder'   => __('wife/husband'),
        ), $checkout->get_value( 'relation' ));

    woocommerce_form_field( 'emergency_phone', array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Emergency Phone'),
        'placeholder'   => __('xxxx xxx xxx / xxxx xxxx'),
        ), $checkout->get_value( 'emergency_phone' ));

}

Error checking:

add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');

function my_custom_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['date_of_birth'] )
        wc_add_notice( __( 'Please enter your date of birth' ), 'error' );
    if ( ! $_POST['emergency_contact_name'] )
        wc_add_notice( __( 'Please enter your Emergency Contact Name' ), 'error' );     
    if ( ! $_POST['relation'] )
        wc_add_notice( __( 'Please enter how your Emergency Contact is related to you' ), 'error' );
    if ( ! $_POST['emergency_phone'] )
        wc_add_notice( __( 'Please enter the phone number of your Emergency Contact' ), 'error' );              
}

(Hopefully) update the user meta upon checkout:

add_action( 'woocommerce_checkout_update_user_meta', 'my_custom_checkout_field_update_user_meta' );

function my_custom_checkout_field_update_order_meta( $order_id ) {
    if ( !empty( $_POST['date_of_birth'] ) ) {
        $dob = sanitize_text_field( $_POST['date_of_birth'] );
        update_user_meta( $current_user->ID, 'date_of_birth', $dob);
    }
    if ( ! empty( $_POST['emergency_contact_name'] ) ) {
        update_user_meta( $user_id, 'emergency_contact_name', sanitize_text_field( $_POST['emergency_contact_name'] ) );
    }
    if ( ! empty( $_POST['relation'] ) ) {
        update_user_meta( $user_id, 'relation', sanitize_text_field( $_POST['relation'] ) );
    }
    if ( ! empty( $_POST['emergency_phone'] ) ) {
        update_user_meta( $user_id, 'emergency_phone', sanitize_text_field( $_POST['emergency_phone'] ) );
    }           
}

Unfortunately, the user meta custom fields are not updated when I checkout.

I can update the order meta custom fields with the following code:

add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );

function my_custom_checkout_field_update_order_meta( $order_id ) {
    if ( ! empty( $_POST['date_of_birth'] ) ) {
        update_post_meta( $order_id, 'Date Of Birth', sanitize_text_field( $_POST['date_of_birth'] ) );
    }
    if ( ! empty( $_POST['emergency_contact_name'] ) ) {
        update_post_meta( $order_id, 'Emergency Contact Name', sanitize_text_field( $_POST['emergency_contact_name'] ) );
    }
    if ( ! empty( $_POST['relation'] ) ) {
        update_post_meta( $order_id, 'Emergency Relation', sanitize_text_field( $_POST['relation'] ) );
    }
    if ( ! empty( $_POST['emergency_phone'] ) ) {
        update_post_meta( $order_id, 'Emergency Phone', sanitize_text_field( $_POST['emergency_phone'] ) );
    }           
}

However, we need the custom fields in the user meta, not the order meta.

Can you see what is wrong with the code that saves custom fields upon checkout to the user meta?

Thanks.

Answer

Reigel picture Reigel · Apr 19, 2016

first, you should add your custom fields like this: (use woocommerce_checkout_fields filter)

function reigel_woocommerce_checkout_fields( $checkout_fields = array() ) {

    $checkout_fields['order']['date_of_birth'] = array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Date of Birth'),
        'placeholder'   => __('dd/mm/yyyy'),
        'required'      => true, 
        );

    return $checkout_fields;
}
add_filter( 'woocommerce_checkout_fields', 'reigel_woocommerce_checkout_fields' );

adding 'required' and setting it to true will have the same effect with how you check if this field is set or not. (your "Error checking")

then in your woocommerce_checkout_update_user_meta, the first parameter is not $order_id but the $customer_id. You should know too that the second parameter is $posted. $posted contains the $_POST[] data. Including your custom fields if you did the code above.

function reigel_woocommerce_checkout_update_user_meta( $customer_id, $posted ) {
    if (isset($posted['date_of_birth'])) {
        $dob = sanitize_text_field( $posted['date_of_birth'] );
        update_user_meta( $customer_id, 'date_of_birth', $dob);
    }
}
add_action( 'woocommerce_checkout_update_user_meta', 'reigel_woocommerce_checkout_update_user_meta', 10, 2 );