Search code examples
phpwordpresswoocommercecustom-fieldsorders

Save Order item custom field in Woocommerce Admin order pages


I have add custom fields in back office order for each line products : Image
(source: com-pac.ovh)

My code:


add_action( 'woocommerce_before_order_itemmeta', 'cfwc_create_custom_field' );
function cfwc_create_custom_field() {

    $args = array(
        'id' => 'custom_text_field_title',
        'label' => __( 'Custom Text Field Title', 'cfwc' ),
        'class' => 'cfwc-custom-field',
        'desc_tip' => true,
        'description' => __( 'Enter the title of your custom text field.', 'ctwc' ),
    );

    woocommerce_wp_text_input( $args );
}

My problem is that I don't know how to save this fields.

Any help?


Solution

  • Update 2024 (Using CRUD Objects methods, works with High Performance Orders Storage)

    To add and save a custom field to order "line items" in admin order edit pages you will use something like:

    
    // Add a custom field
    add_action( 'woocommerce_before_order_itemmeta', 'add_order_item_custom_field', 10, 2 );
    function add_order_item_custom_field( $item_id, $item ) {
        // Targeting line items type only
        if( $item->get_type() !== 'line_item' ) return;
    
        $post_key = 'cfield_oitem_'.$item_id;
    
        woocommerce_wp_text_input( array(
            'id'            => $post_key,
            'label'         => __( 'Custom Text Field Title', 'text_domain' ),
            'description'   => __( 'Enter the title of your custom text field.', 'text_domain' ),
            'desc_tip'      => true,
            'class'         => 'woocommerce',
            'value'         => $item->get_meta('_custom_field'),
        ) );
    }
    
    // Save the custom field value (Compatible with HPOS)
    add_action('woocommerce_before_save_order_item', 'save_order_item_custom_field_value', 100 );
    function save_order_item_custom_field_value( $item ){
        $post_key = 'cfield_oitem_'.$item->get_id();
    
        if( isset($_POST[$post_key]) ) {
            $item->update_meta_data( '_custom_field', sanitize_text_field($_POST[$post_key]) );
        }
    }
    

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

    To display this input field after all displayed item metadata, replace:

    add_action( 'woocommerce_before_order_itemmeta', 'add_order_item_custom_field', 10, 2 );
    

    with:

    add_action( 'woocommerce_after_order_itemmeta', 'add_order_item_custom_field', 10, 2 );
    

    Additions

    Optionally Keep the new meta key/value as hidden in backend

    add_filter( 'woocommerce_hidden_order_itemmeta', 'additional_hidden_order_itemmeta', 10, 1 );
    function additional_hidden_order_itemmeta( $args ) {
        $args[] = '_custom_field';
        return $args;
    }
    

    Optionally Change the displayed meta key label

    add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 20, 3 );
    function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
        // Change displayed label for specific order item meta key
        if( is_admin() && $item->get_type() === 'line_item' && $meta->key === '_custom_field' ) {
            $display_key = __("Some label", "woocommerce" );
        }
        return $display_key;
    }