WooCommerce order items and order item meta by key
Table of Contents
In this tutorial I want to talk about WooCommerce order items. To understand what I mean, just look at the screenshot below:
You can see the Edit Order page with products purchased, shipping and fee. All of these are order items:
- products –
line_item
type, - shipping –
shipping
type, - fee –
fee
type
Order items has their own tables in WordPress database – {prefix}woocommerce_order_items
and {prefix}woocommerce_order_itemmeta
.
What is the reason in creating a separate database table for products in an order than linking them by IDs? Actually the reason is really simple. Let’s say that someone purchased a snowboard from your store. A couple days ago the price of this snowboard has been changed… But we can not change it in that order! Did you get it?
How to do some magic with Order Items in code
Get
Let’s begin with WC_Order’s get_items()
that returns all products in an order. But why? – order items are not only products, shipping and fee are also order items, aren’t they?
Sure, get_items()
returns only products because it has the only parameter $types
that is line_item
by default. Anyway we can pass an array instead: get_items( array('line_item', 'fee', 'shipping')
.
$order_items = $order_object->get_items( array('line_item', 'fee', 'shipping') ); if ( !is_wp_error( $order_items ) ) { foreach( $order_items as $item_id => $order_item ) { echo $order_item->get_order_id(); echo $order_item->get_name(); echo $order_item->get_total(); // item price echo $order_item->get_type(); // line_item | fee | shipping // for products only: echo $order_item->get_quantity(); // or $order_item['quantity']; echo $order_item->get_product_id(); // or $order_item['product_id']; echo $order_item->get_variation_id(); // or $order_item['variation_id']; echo $order_item->get_product(); // get the associated product } }
Add
Actually you can add the order items to an order when you create it with wc_create_order()
function. But today we’re not talking about the orders themselves, so I suppose that an order with some $order_id
is already exists and we want to add order items to it in the code:
// add an order item linked to a product $order_item_id = wc_add_order_item( $order_id, array( 'order_item_name' => 'Some product', 'order_item_type' => 'line_item', // product )); wc_add_order_item_meta( $order_item_id, '_qty', 2, true ); // quantity wc_add_order_item_meta( $order_item_id, '_product_id', 13, true ); // ID of the product // you can also add "_variation_id" meta wc_add_order_item_meta( $order_item_id, '_line_subtotal', 10, true ); // price per item wc_add_order_item_meta( $order_item_id, '_line_total', 20, true ); // total price // add a fee order item $order_item_id = wc_add_order_item( $order_id, array( 'order_item_name' => 'Some fee', 'order_item_type' => 'fee', )); wc_add_order_item_meta( $order_item_id, '_fee_amount', 20, true ); wc_add_order_item_meta( $order_item_id, '_line_total', 20, true ); $order = new WC_Order( $order_id ); $order->calculate_totals();
If you would like to add a shipping order item, use shipping
order_item_type and cost
parameter to pass the shipping price and method_id
as a shipping type.
Update
To update the existing order items you can use wc_update_order_item( $item_id, $args)
, where $args
is the array with the same parameters wc_add_order_item()
accepts and wc_update_order_item_meta( $item_id, $key, $value, $prev_value )
.
If you want to reattach an order item to another order, this code will help:
wc_update_order_item( $order_item_id, array( 'order_id' => $new_order_id ) );
If you just would like to change the quantity of the product from the above example, you can use this code:
wc_update_order_item_meta( $order_item_id, '_qty', 3 ); wc_update_order_item_meta( $order_item_id, '_line_total', 30 );
Remove
The cool thing is that when you remove an order item with wc_delete_order_item( $order_item_id )
you shouldn’t care about deleting all its metadata, because it will be removed automatically.
But if you just want to delete some meta, wc_delete_order_item_meta( $item_id, $key, $value, $delete_all )
. The required parameters are only $item_id
and $key
.
Add a custom product meta to an associated order item automatically
It is very easy to do, woocommerce_add_order_item_meta
action hook will help you with it:
add_action( 'woocommerce_add_order_item_meta', 'misha_order_item_meta', 10, 2 ); // $item_id – order item ID // $cart_item[ 'product_id' ] – associated product ID (obviously) function misha_order_item_meta( $item_id, $cart_item ) { // get product meta $event_time = get_post_meta( $cart_item[ 'product_id' ], 'event_time', true ); // if not empty, update order item meta if( ! empty( $event_time ) ) { wc_update_order_item_meta( $item_id, 'event_time', $event_time ); } }
How to check if order item meta is added?
With the help of this tutorial you can create a column with purchased products and print your order item meta by key
foreach( $order_items as $order_item_id => $order_item ) { echo wc_get_order_item_meta( $order_item_id, 'event_time'); }
Another way – check your Edit Order page