phpwoocommercehook-woocommercecheckoutorders

Why are some checkout action hooks not working in WooCommerce?


I'm using the following code to save the value of a hidden input field having as attribute name "custom_form_data":

add_action('woocommerce_checkout_update_order_meta', 'save_custom_form_data_to_order');
function save_custom_form_data_to_order($order_id) {
    if (isset($_POST['custom_form_data'])) {
        $custom_form_data = sanitize_text_field($_POST['custom_form_data']);
        update_post_meta($order_id, 'custom_form_data', $custom_form_data);
    }
}

But the submitted value is not saved to the database. I Checked on wp_postmeta and wp_wc_orders_meta tables.

Why is woocommerce_checkout_update_order_meta hook not working?


Solution

  • This can be related to 2 different things:

    1. High-Performance Order Storage is enabled:

    Note that High-Performance Order Storage (HPOS) is now enabled by default.

    If HPOS is enabled, you need to use instead a compatible hook, like:

    add_action('woocommerce_checkout_create_order', 'save_custom_form_data_to_order');
    function save_custom_form_data_to_order( $order ) {
        if ( isset($_POST['custom_form_data']) ) {
            $order->update_meta_data( 'custom_form_data', sanitize_text_field($_POST['custom_form_data']) );
        }
    }
    

    Or you could use alternatively the following (requires using the save() method):

    add_action('woocommerce_checkout_order_created', 'save_custom_form_data_to_order');
    function save_custom_form_data_to_order( $order ) {
        if ( isset($_POST['custom_form_data']) ) {
            $order->update_meta_data( 'custom_form_data', sanitize_text_field($_POST['custom_form_data']) );
            $order->save();
        }
    }
    

    With HPOS, WordPress Post meta functions doesn't work any more as WooCommerce orders use custom database tables for better performances.

    So HPOS requires to use WC_Data, WC_Abstract_Order or WC_Order methods on the WC_Order object.

    So to get/read the value from your custom field, you will use something like:

    $order = wc_get_order( $order_id ); // If needed get the WC_Order object
    
    $value = $order->get_meta('custom_form_data'); // Get custom field value
    

    1. Checkout Blocks is enabled:

    Note that Checkout Blocks is now enabled by default, and only allows very few customizations.

    The following action hooks won't work when using Checkout Blocks:

    The alternative is to switch back to legacy classic Checkout (shortcode).