Saving form data from a custom WooCommerce My Account tab

Viewed 1212

I have created a new Member Details tab in My Account and populated the tab with form fields to gather member details like hobbies, birthday, etc. These details are then displayed on the My Account Dashboard.

How can I save the data that is submitted on the new Member Details tab?

Many sites have examples how to display info on new tabs but I couldn't find any that show how to submit and save form data.

function add_custom_fields() {
    $user = wp_get_current_user();
    ?>
    <form id="edit_member_details" method="post">
        <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
            <label for="member_hobbies"><?php _e( 'Member Hobbies', 'woocommerce' ); ?>
            <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="member_hobbies" id="member_hobbies" value="<?php echo esc_attr( $user->member_hobbies ); ?>" />
        </p>
        <p>
            <button type="submit" class="button" name="save_member_details" value="<?php esc_attr_e( 'Save member details', 'woocommerce' ); ?>"><?php esc_html_e( 'Save member details', 'woocommerce' ); ?></button>
            <input type="hidden" name="woocommerce_edit_member_details" value="save_member_details" />
        </p>
    </form>
    <?php
}

add_action( 'woocommerce_save_account_details', 'save_member_details', 12, 1 );
function save_member_details( $user_id ) {
    if( isset( $_POST['member_hobbies'] ) )
        update_user_meta( $user_id, 'member_hobbies', sanitize_text_field( $_POST['member_hobbies'] ) );
}
1 Answers

The way Woocommerce does their form submission handling is by creating classes which are then hooked into either the wp or template_redirect actions. You can see this for yourself by looking at WC_Form_Handler.

Depending on your approach, you can follow a similar strategy and create a class or function that is hooked early to process your form data. For example

add_action('wp', 'my_form_handler');
function my_form_handler() {
   // read in my post data

   // process my data.

   // optionally redirect
}

One issue that you'll run into here is that this hook will run every time wp or template_redirect is called, which is every single page load. Woocommerce handles this by looking for nonces, post fields, and using the is_* functions. One strategy I use is to begin my function with

if(filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') {
    return;
}

This will cause the function to exit out if we're not detecting a POST action on page.

If you decide to perform form validation, you'll run into issues with reporting errors if you opt to use wc_add_notice, especially if you decide to redirect after form processing. If you do redirect after using wc_add_notice, your notice will be lost, as notices do not persist across page loads.

Related