phpwordpresswoocommerceordersmeta-boxes

Add a custom Metabox to WooCommerce admin orders with HPOS enabled


I'm trying to add a new meta box on the woocommerce order page in the dashboard.

add_action( 'add_meta_boxes', 'add_meta_box_wrapper' );
function add_meta_box_wrapper() {
    add_meta_box( 'custom_meta_box', __( 'Facture' ), 'metabox_content', 'shop_order', 'side', 'core');
}

function metabox_content() {
    echo '<a>Test button</a>';
}

This is the code I tried, but it doesn't seem work.

If I change the fourth parameter of the add_meta_box function to post, I can get it to display in the post edit page so the problem must be with the slug I'm using. I also tried changing that parameter to 'wc-orders' as well as changing the action hook to 'add_meta_boxes_shop_order' and 'add_meta_boxes_wc-orders' like some people suggest in other threads, but nothing seems to work.

Anyone has an idea?


Solution

  • This issue is related to the fact that High Performance Order Storage (HPOS) is enabled, so you need something a bit different to add a custom Metabox to admin orders:

    use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
    
    // Add a custom metabox
    add_action( 'add_meta_boxes', 'admin_order_custom_metabox' );
    function admin_order_custom_metabox() {
        $screen = class_exists( '\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController' ) && wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled()
            ? wc_get_page_screen_id( 'shop-order' )
            : 'shop_order';
    
        add_meta_box(
            'custom',
            'Custom Meta Box',
            'custom_metabox_content',
            $screen,
            'side',
            'high'
        );
    }
    
    // Metabox content
    function custom_metabox_content( $object ) {
        // Get the WC_Order object
        $order = is_a( $object, 'WP_Post' ) ? wc_get_order( $object->ID ) : $object;
    
        echo '<p>Number (ID): '.$order->get_order_number().'<p>';
        echo '<a>Test button</a>';
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works with or without HPOS enabled.

    enter image description here


    Example with a custom input field

    Replace the 2nd function with:

    // Metabox content
    function custom_metabox_content( $object ) {
        // Get the WC_Order object
        $order = is_a( $object, 'WP_Post' ) ? wc_get_order( $object->ID ) : $object;
    
        echo '<p>
        <label for="number_id">' . __('Number ID') . ':<label><br>
        <input type="text" id="number_id" class="number_id" name="number_id" value="' . $order->get_meta('number_id') . '" />
        <p>';
    }
    
    // Save custom field value
    add_action( 'woocommerce_process_shop_order_meta', 'save_number_id_value', 20 );
    function save_number_id_value( $order_id ) {
        $order = wc_get_order( $order_id ); // Get the WC_Order object
        
        if ( isset($_POST['number_id']) ) {
            $order->update_meta_data('number_id', sanitize_text_field($_POST['number_id']));
            $order->save();
        }
    }
    

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


    Related documentation: High Performance Order Storage Upgrade Recipe Book

    Related: