skip to Main Content

I’m trying to add some custom meta_data to a WooCommerce Order, by running a Order action.

Here is my code:

function custom_add_order_actions( $actions ){
    global $theorder;
    $actions['my_custom_action'] = 'My custom action';
    return $actions;
}
add_action( 'woocommerce_order_actions', 'custom_add_order_actions' );



function custom_add_single_action( $order ){

    // Non of these change anything on the order
    $order->set_billing_first_name( 'A new test name' );
    $order->update_post_meta( 'a_test_field', 'Test field value' );
    update_post_meta( $order->get_id(), 'a_test_field', 'Some other value' );

    // $order->save(); // I even tried adding this as well, but it doesn't change anything.
}
add_action( 'woocommerce_order_action_my_custom_action', 'custom_add_single_action' );

How do I change the order (or specifically, post_meta fields for an order) from inside an action?


A example

Imagine that I add a post_meta field, with the field name (key): a_test_field.
It’s currently an ACF-field, but it’s the same for regular WordPress custom fields.

If I change the value of the field and press ‘Update’, then the value changes:

update order meta field - WooCommerce

So far so good. Now the value of the field is ‘Foobar’.

What’s wierd is that even if I do this:

add_action( 'woocommerce_order_action_my_custom_action', 'custom_add_single_action' );
function custom_add_single_action( $order ){
    update_post_meta( $order->get_id(), 'a_test_field', 'A new value' );
    die(); // This die is vital, to make the change in the database.
}

Then I can see the value change in the database to ‘A new value’.

But if I just do this:

add_action( 'woocommerce_order_action_my_custom_action', 'custom_add_single_action' );
function custom_add_single_action( $order ){
    $order->update_post_meta( 'a_test_field', 'A new value' );
    // No die(); here... 
}

Then the value remains ‘Foobar’ in the database.

2

Answers


  1. Sorry but the following lightly revisited code works (Selecting the action and click on the button arrow):

    enter image description here

    add_action( 'woocommerce_order_actions', 'add_custom_order_action' );
    function add_custom_order_action( $actions ){
        $actions['my_custom_action'] = __('My custom action', 'WooCommerce');
    
        return $actions;
    }
    
    add_action( 'woocommerce_order_action_my_custom_action', 'triggered_custom_order_action' );
    function triggered_custom_order_action( $order ){
        $order->update_meta_data( '_test_1_custom_field', 'AAFFBB9977' );
        $order->save();
    
        update_post_meta( $order->get_id(), '_test_2_custom_field', 'Some other value' );
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.

    enter image description here

    Note: Order actions are mostly used for some other things than what you are trying to do.


    Now when using a meta box with an input field (as you are showing), on submit, you should save that field value using the action hook save_post_shop_order like in those related threads:

    Login or Signup to reply.
  2. I’ve just had a similar issue and the solution for me was to replace $order in the handler function with the same name I used in the function that declares the custom action. In this case, $theorder:

    function custom_add_order_actions( $actions ){
       global $theorder;
       $actions['my_custom_action'] = 'My custom action';
       return $actions;
    }
    add_action( 'woocommerce_order_actions', 'custom_add_order_actions' );
        
    function custom_add_single_action( $theorder ){
        
      $theorder->set_billing_first_name( 'A new test name' );
      $theorder->update_post_meta( 'a_test_field', 'Test field value' );
      update_post_meta( $theorder->get_id(), 'a_test_field', 'Some other value' );
        
      $theorder->save();
    }  add_action('woocommerce_order_action_my_custom_action','custom_add_single_action' );
    

    Also, there’s a problem when the custom field is visible on the Order Edit page, as in ACF fields. When calling $theorder->save(), the page will refresh and it will update the meta according to what’s visible on the page, which is the old value of the field, or empty. This is why the accepted answer works: the field doesn’t have an input on the order page.
    A possible solution for this is to add the metadata in a field that’s only present in the database, and show the data in a note:

    function custom_add_single_action( $theorder ){
    
      $theorder->update_post_meta( 'a_test_field_hidden', 'Test field value' );
      $theorder->add_order_note( 'Visible field: Test field value.' 
    
      $theorder->save();
    }  add_action('woocommerce_order_action_my_custom_action','custom_add_single_action' );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search