Order Items Tutorial

If you open any edit order page in WooCommerce, you will find attached products in it… but actually it is not products at all.

/10 comments

Hey 🎉,

In this tutorial I want to talk about WooCommerce order items. To understand what I mean, just look at the screenshot below:

WooCommerce Order Items on the Edit order page: line items (products), shipping and fee.

You can see the Edit Order page with products purchased, shipping and fee. All of these are order items:

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
	}
}

You can add a column with order items and play with code.

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?

How to add a possibility for customers to provide their custom data to each product purchase. Example with names on T-Shirts

Please look on the screenshots below to understand what we are going to do step by step.

/*
 * Step 1. Add an input field just before the "Add to cart" button
 */
add_action( 'woocommerce_before_add_to_cart_button', 'misha_before_add_to_cart_field' );
 
function misha_before_add_to_cart_field() {
	global $product; // awesome - we have a global product object here
 
	// let's add the input field only for products in a specific category with "t-shirts" slug
	if ( !has_term('t-shirts', 'product_cat', $product->get_id() ) ) {
		return;
	}
 
	echo '<div class="misha-before-add-to-cart-field">
		<label for="name-on-t-shirt">Name on T-Shirt: </label>
		<input type="text" id="name-on-t-shirt" name="name-on-t-shirt" placeholder="Enter a name" maxlength="15">
	</div>';
 
}
 
/*
 * Step 2. Save the provided field value to the cart data
 */
add_filter( 'woocommerce_add_cart_item_data', 'misha_save_field_value_to_cart_data', 10, 3 );
 
function misha_save_field_value_to_cart_data( $cart_item_data, $product_id, $variation_id ) {
 
	if ( !empty( $_POST['name-on-t-shirt'] ) ) { // here could be another validation if you need
		$cart_item_data['name-on-t-shirt'] = sanitize_text_field( $_POST['name-on-t-shirt']);
	}
 
	return $cart_item_data;
 
}
 
/*
 * Step 3. Display "Name on T-shirt" on the pages: Cart, Checkout, Order Received
 */
add_filter( 'woocommerce_get_item_data', 'misha_display_field', 10, 2 );
 
function misha_display_field( $item_data, $cart_item ) {
 
	if ( !empty( $cart_item['name-on-t-shirt'] ) ) {
		$item_data[] = array(
			'key'     => 'Name on T-shirt',
			'value'   => $cart_item['name-on-t-shirt'],
			'display' => '', // in case you would like to display "value" in another way (for users)
		);
	}
 
	return $item_data;
 
}
 
/*
 * Step 4. Add the field value to the Order Item meta
 */
add_action( 'woocommerce_checkout_create_order_line_item', 'misha_add_order_item_meta', 10, 4 );
 
function misha_add_order_item_meta( $item, $cart_item_key, $values, $order ) {
 
	if ( !empty( $values['name-on-t-shirt'] ) ) {
		$item->add_meta_data( 'Name on a T-Shirt', $values['name-on-t-shirt'] );
	}
 
}

Have a question? Scroll down to comments 👇

More WooCommerce Tutorials

Misha Rudrastyh

Misha Rudrastyh

I love WordPress, WooCommerce and Gutenberg so much. 10 yrs of experience.

Need some custom developer help? Let me know

Follow Misha

Need some help with WooCommerce?

If you need some professional developer help, I will be happy to assist you.

Contact me Who I am?

Comments — 10

Leave a comment

php js HTML CSS Code