17

Need to add custom meta to order items. Googled it and most articles says to use "woocommerce_add_order_item_meta" hook. This hook is deprecated in the newest version 2.3.7. Someone, please tell me which hook to use instead.

http://docs.woothemes.com/wc-apidocs/function-woocommerce_add_order_item_meta.html

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
user3339988
  • 404
  • 2
  • 5
  • 12

8 Answers8

25

2017/2018 THE RIGHT WAY (Using new CRUD setters and Getters methods)

Related: Replace woocommerce_add_order_item_meta hook in Woocommerce 3.4

Since woocommerce 3 that has improved many things making drastic changes, the action hook woocommerce_add_order_item_meta still work perfectly even in woocommerce version 3.3+.

This hook is enabled by WC_Checkout class methods and related functions in the checkout process and not in WC_Order Class where cart data is not anymore available.

Now as Woocommmerce 3 has introduced new CRUD setters and getters methods, the similar replacement hook to be used is woocommerce_checkout_create_order_line_item that has similar useful arguments as cart data.

The woocommerce_new_order_item is really NOT convenient as cart data is not accessible.

Let see how to work with woocommerce_checkout_create_order_line_item. It has 4 available arguments:

  • $item is an instance of WC_Order_Item_Product new introduced Class
  • $cart_item_key is the cart item unique hash key
  • $values is the cart item
  • $order an instance of the WC_Order object (This is a very useful additional argument in some specific cases)

In this hook we will replace the old working functions wc_add_order_item_meta() by the new WC_Data update_meta_data() method to be used with $item argument.

Example:

## --- New way --- ##
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
    // Get a product custom field value
    $custom_field_value = get_post_meta( $item->get_product_id(), '_meta_key', true );
    // Update order item meta
    if ( ! empty( $custom_field_value ) ){
        $item->update_meta_data( 'meta_key1', $custom_field_value );
    }
    // … … Or … …

    // Get cart item custom data and update order item meta
    if( isset( $values['custom_data'] ) ) {
        $item->update_meta_data( 'meta_key2', $values['custom_data'] );
    }
}

Finally we can do the same with old way using woocommerce_add_order_item_meta hook as it has nearly the same useful arguments:

## --- Old way --- ##
add_action( 'woocommerce_add_order_item_meta', 'custom_add_order_item_meta', 20, 3 );
function custom_add_order_item_meta( $item_id, $values, $cart_item_key ) {
    // Get a product custom field value
    $custom_field_value = get_post_meta( $values['data']->get_id(), '_meta_key', true );
    // Update order item meta
    if ( ! empty( $custom_field_value ) ){
        wc_add_order_item_meta( $item_id, 'meta_key1', $custom_field_value );
    }
    // … … Or … …

    // Get cart item custom data and update order item meta
    if( isset( $values['custom_data'] ) ) {
        wc_add_order_item_meta( $item_id, 'meta_key2', $values['custom_data'] );
    }
}

Conclusion: woocommerce_checkout_create_order_line_item is the right replacement hook to be used with WooCommerce 3+ and that new CRUD setters and getters methods.

Community
  • 1
  • 1
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • It's working fine, thanks. However some parameters are not fully available. The `$order` parameter doesn't have an ID for example and apparently we can't have the `$item_id` as well – Pablo S G Pacheco Jan 30 '19 at 20:11
  • @PabloSGPacheco Sorry but all parameters are available: To get the **Order ID**, simply use `$order_id = $order->get_id();` and for the **Item ID** simply use `$item_id = $item->get_id();`… – LoicTheAztec Jan 30 '19 at 20:33
  • 1
    @LoicTheAztec Thanks for the feedback, but I get zero in both cases. And maybe it makes some sense. When `woocommerce_checkout_create_order_line_item` is triggered the order hasn't been created yet. Am I right? – Pablo S G Pacheco Jan 30 '19 at 21:09
  • @PabloSGPacheco The order is not saved to the database yet, as the method [`WC_Order` `save()`](https://docs.woocommerce.com/wc-apidocs/source-class-WC_Order.html#207-228) is used later at the end of [`WC_Checkout` `create_order()`](https://docs.woocommerce.com/wc-apidocs/source-class-WC_Checkout.html#255-345) method. – LoicTheAztec Jan 30 '19 at 22:21
  • @LoicTheAztec Thanks, so it means we can't have the order ID nor the item ID, correct? – Pablo S G Pacheco Feb 01 '19 at 16:42
  • @PabloSGPacheco I am not so sure, you need to try that using for example `woocommerce_checkout_create_order` hook and trying to save `$order->get_id()` value as custom meta data to see if you get an integer number different from zero... – LoicTheAztec Feb 01 '19 at 16:48
18

If you look at wc-deprecated-functions.php you will see

/**
 * @deprecated
 */
function woocommerce_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
    return wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique );
}

Basically, the function was renamed to wc_add_order_item_meta(), so if you need the function then use that. The action hook was not renamed and remains in class-wc-checkout.php as:

// Allow plugins to add order item meta
do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • 2
    The hook is now deprecated, so this answer is not correct – Tofandel Jun 25 '19 at 09:19
  • 1
    It was the correct answer in 2015. :) But, it looks like @LoicTheAztec already has an updated and correct answer, so everyone should defer to that: https://stackoverflow.com/a/49419394/383847 – helgatheviking Jun 26 '19 at 13:15
5

It seems that the hook is now also deprecated as of version 3.0.4. I'm getting this notification:

The The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.0.4. Replace with woocommerce_new_order_item.

I have replaced the action name 'woocommerce_add_order_item_meta' with 'woocommerce_new_order_item' in an add_action statement in an offending plugin, and the deprecation notification disappears, The problem is that some parameters now appear inside a legacy_values array. I use the plugin YITH WooCommerce Product Add Ons, and the product meta data that should be attached to an order is not picked up by the plugin and therefore not stored with the order. So until this is fixed in the plugin you have to live with the deprecation notification.

  • Sorry but `woocommerce_new_order_item` don't replace `woocommerce_add_order_item_meta` … so is this an answer? or a question?…Kindly, in both case you should update this with something right and tested … or delete it if not. Thanks – LoicTheAztec May 04 '17 at 11:01
  • 2
    OK, to be clear. The hook is deprecated and you get an advice in the deprecation message to use another hook. But as @LoicTheAztec says, this hook is not a perfect replacement, because the parameters appear differently. So: don't follow the advice in the deprecation message (unless you have full control of the code). I always try to get rid of all notifications, but in this case I will have to live with it – Christer Fernstrom May 05 '17 at 13:28
4

I know this has been answered and there is an accepted reply already. I just wanted to give another way to handle this without actually getting a deprecated message (see reference);

add_action('woocommerce_new_order_item', 'saveMetaData', 10, 3); // or use just 2 instead of 3; if you don't need order id

/**
 * Add meta to order item
 *
 * @param int $itemId
 * @param WC_Order_Item_Product|WC_Order_Item_Shipping $item
 * @param int @orderId
*/
function saveMetaData($itemId, $item, $orderId)
{
    if (!isItemValid($item))
    {
        return;
    }

    wc_add_order_item_meta($itemId, 'my_custom_data', $item->legacy_values['my_custom_data']);
}

/**
 * @param WC_Order_Item_Product|WC_Order_Item_Shipping $item
 *
 * @return bool
*/
function isItemValid($item)
{
    return (
        $item instanceof WC_Order_Item_Product &&
        isset($item->legacy_values) &&
        isset($item->legacy_values['my_custom_data']) &&
        !empty($item->legacy_values['my_custom_data'])
    );
}
1

Your specific use case isn't very clear (you didn't specify when or where you need to add this meta info), but you can use woocommerce_checkout_update_order_meta during checkout.

Read more in customizing checkout fields.

rnevius
  • 26,578
  • 10
  • 58
  • 86
  • Sorry about that. i have a custom post type "service" and when customer fills in the services form, i have to add a product(plan) to cart and pass service id to that product. which I have completed, now want to pass that id to order item meta. Cart will have other products too... – user3339988 Apr 16 '15 at 06:47
1

No it seems like the hook is also deprecated: PHP Error: The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.1.2. Replace with woocommerce_new_order_item.

I also cannot find it here: https://docs.woocommerce.com/wc-apidocs/hook-docs.html

tperschon
  • 11
  • 1
1

I wanted to add on to Ilgıt Yıldırım's answer: in my case, my custom values did not exist in the item->legacy_values array. To fix this, I used the woocommerce_checkout_create_order_line_item hook to add the custom values to the item prior to calling the woocommerce_new_order_item hook. Here is an example of that:

add_action( 'woocommerce_checkout_create_order_line_item', 'save_values_in_item', PHP_INT_MAX, 4 );

function save_values_in_item( $item, $cart_item_key, $values, $order ) {

                $item->myCustomValues = $values;

}

//THEN call the new hook: add_action( 'woocommerce_new_order_item', 'add_product_input_fields_to_order_item_meta_wc3', PHP_INT_MAX, 3 );

function add_product_input_fields_to_order_item_meta_wc3( $item_id, $item, $order_id ) {

            if ( isset( $item->myCustomValues ) ) 
            {
                  //iterate through array and place desired values into the meta data using the wc_add_order_item_meta function
            }

}

sc8704
  • 11
  • 1
0

Just to make things clear, this function was deprecated, but the hook is still ok

Pablo S G Pacheco
  • 2,550
  • 28
  • 28