Skip to content

Instantly share code, notes, and snippets.

@RadGH
Last active April 27, 2024 17:25
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save RadGH/e3444fc661554a0f8c6f to your computer and use it in GitHub Desktop.
Save RadGH/e3444fc661554a0f8c6f to your computer and use it in GitHub Desktop.
Get and set custom cart item/product information prior to WooCommerce checkout, and carry those valus over to Order Item Metadata.
<?php
// UPDATE: Stefan from Stack Overflow has explained a better way to handle cart item data.
// See http://stackoverflow.com/a/32327810/470480
// ----------------------
/*
Instructions:
1) Save data when adding to cart
When adding an item to your cart, use ld_woo_set_item_data. The best action for this to occur is
"woocommerce_add_to_cart". The first parameter for this action contains the "cart_item_key",
which is required for the function.
// Save a custom field called "class-date" to the item added to the cart
$date = $_REQUEST['class-date'];
ld_woo_set_item_data( cart_item_key, "class-date", $date );
2) Retrieve item data before checkout
At any point you may retrieve this data using "ld_woo_get_item_data". If you wantto get a list of
all cart items, use: "WC()->cart->get_cart()". This will return an array. The keys are the
"cart_item_key" which will be needed.
3) Display data assigned to the item after the order is complete
When a user checks out, their "cart" is emptied and what they had purchased becomes an "order"
instead. At this point, all of the custom item data is stored as item meta using the key
"_ld_woo_product_data".
If your custom data should be displayed to customers or administrators (as a regular Item Meta),
you want to add your own custom meta instead. To do this, use the action
"woocommerce_add_order_item_meta" and retrieve our custom item data, and add it as item meta
on your own.
// Save custom field as public item meta, viewable on invoices, receipts, and within the dashboard
function custom_add_date_order_meta( $item_id, $values, $cart_item_key ) {
// Ensure the product supports our custom field
if ( !custom_product_has_date( $values['product_id'] ) ) return;
// Retrieve the date which was assigned previously
$date = woo_get_item_data( $cart_item_key, 'class-date' );
// If the date is available, save it as item metadata. Otherwise use a default value (optional).
// Note that item meta key can have uppercase characters and spaces. This is not a slug or HTML id.
if ( $date ) wc_add_order_item_meta( $item_id, "Class Date", $date );
else wc_add_order_item_meta( $item_id, "Class Date", '[error]' );
}
add_action('woocommerce_add_order_item_meta', 'custom_add_date_order_meta', 10, 3 );
Functions:
ld_woo_get_item_data( $cart_item_key, [$key, $default] )
Returns cart item data for the specified cart item. If $key is provided, a single value is returned.
Otherwise, an array of all cart item data is returned.
ld_woo_set_item_data( $cart_item_key, $key, $value )
Sets the data for a cart item by key. Similar to post meta, but based on session.
ld_woo_remove_item_data( $cart_item_key, [$key] )
Removes cart item data, a specific key if $key is provided, otherwise the entire cart item's data variable is removed.
* Called automatically when product is removed from the cart
ld_woo_convert_item_session_to_order_meta()
Occurs during checkout, item data is automatically converted to order metadata, stored under the "_ld_woo_product_data"
*/
function ld_woo_get_item_data( $cart_item_key, $key = null, $default = null ) {
$data = (array)WC()->session->get( '_ld_woo_product_data' );
if ( empty( $data[$cart_item_key] ) ) {
$data[$cart_item_key] = array();
}
// If no key specified, return an array of all results.
if ( $key == null ) {
return $data[$cart_item_key] ? $data[$cart_item_key] : $default;
}else{
return empty( $data[$cart_item_key][$key] ) ? $default : $data[$cart_item_key][$key];
}
}
function ld_woo_set_item_data( $cart_item_key, $key, $value ) {
$data = (array)WC()->session->get( '_ld_woo_product_data' );
if ( empty( $data[$cart_item_key] ) ) {
$data[$cart_item_key] = array();
}
$data[$cart_item_key][$key] = $value;
WC()->session->set( '_ld_woo_product_data', $data );
}
function ld_woo_remove_item_data( $cart_item_key = null, $key = null ) {
$data = (array)WC()->session->get( '_ld_woo_product_data' );
// If no item is specified, delete *all* item data. This happens when we clear the cart (eg, completed checkout)
if ( $cart_item_key == null ) {
WC()->session->set( '_ld_woo_product_data', array() );
return;
}
// If item is specified, but no data exists, just return
if ( !isset( $data[$cart_item_key] ) ) {
return;
}
if ( $key == null ) {
// No key specified, delete this item data entirely
unset( $data[$cart_item_key] );
}else{
if ( isset( $data[$cart_item_key][$key] ) ) {
unset( $data[$cart_item_key][$key] );
}
}
WC()->session->set( '_ld_woo_product_data', $data );
}
add_filter( 'woocommerce_before_cart_item_quantity_zero', 'ld_woo_remove_item_data', 10, 1 );
add_filter( 'woocommerce_cart_emptied', 'ld_woo_remove_item_data', 10, 1 );
function ld_woo_convert_item_session_to_order_meta( $item_id, $values, $cart_item_key ) {
// Occurs during checkout, item data is automatically converted to order item metadata, stored under the "_ld_woo_product_data"
$cart_item_data = ld_woo_get_item_data( $cart_item_key );
// Add the array of all meta data to "_ld_woo_product_data". These are hidden, and cannot be seen or changed in the admin.
if ( !empty( $cart_item_data ) ) {
wc_add_order_item_meta( $item_id, '_ld_woo_product_data', $cart_item_data );
}
}
add_action( 'woocommerce_add_order_item_meta', 'ld_woo_convert_item_session_to_order_meta', 10, 3 );
@RadGH
Copy link
Author

RadGH commented Aug 11, 2014

Note that these functions do not utilize "order item data" once checkout has been completed. However, the custom cart data is stored as order item meta after checkout as an array, with the meta key "_lm_product_data". You can retrieve this simply using get_post_meta( $order_id, "_lm_product_data", true );.

Example:

$custom_item_data = get_post_meta( $order_id, "_lm_product_data", true );
echo "This class is scheduled for: " . $custom_item_data['class-date'];

@tmyie
Copy link

tmyie commented May 19, 2015

This looks great. What's the best way to generate or get a $cart_item_key, when setting the item data. Can it be anything?

@RadGH
Copy link
Author

RadGH commented Aug 7, 2015

Sorry I didn't reply. I didn't get any sort of notification that you left a comment!

The "cart_item_key" is a randomly generated key used by WooCommerce. More specifically, when you add an item to your cart you add a new "cart item". This item is then referenced by the "cart_item_key".

To get a list of all cart items, use: "WC()->cart->get_items()". This will return an array of cart items. The key of each item is the cart_item_key.

@j-mccarthy
Copy link

This does look great. I'm attempting to add custom input fields on a separate page after the before checkout. Therefore I want to save the data to the cart itself and not just when an item is added.

Do you have any suggestions on going about this?

@RadGH
Copy link
Author

RadGH commented Dec 10, 2015

Ok, my functions above are for items within the cart. I work around WooCommermce's limitation by storing cart item data in the cart itself. So you don't need my functions at all if you just need to store cart data.

Use these functions:

WC()->session->set(key, value)
WC()->session->get(key)

They are pretty self explanatory, but you can see my usage of them above as well.

@shawnpanda
Copy link

For some reason, ld_woo_get_item_data always returns empty when I use it with woocommerce_get_cart_item_from_session. I wanted to add custom meta to each cart item in the cart page. (I am adding custom meta after the product is added to the cart) Even if I were to just use WC()->session directly, getter function returns empty as well. Do you have any advice or suggestion on solving the issue?

@najidev
Copy link

najidev commented Sep 21, 2016

Hello,
Looks great code,
Could you please how i can use your code my woocommerce website, i want to add meta to each item in cart

Thanks
Naji

@alex94040
Copy link

Note that the method is not called WC()->cart->get_items(). It's called WC()->cart->get_cart(). See https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html

@RadGH
Copy link
Author

RadGH commented Feb 13, 2017

Hi all, sorry I haven't replied to anyone but Gist doesn't give comment notifications so keeping up to date on this is impossible.

I've updated the code above with a reference to Stefan's answer on Stack Overflow. He explains the correct way to do this without abusing the session data. Read his answer here: http://stackoverflow.com/a/32327810/470480

My code still works and you should be fine to continue using it, but if you want to do this "the woocommerce way", see Stefan's answer.

@vpadhariya
Copy link

Hello, Is there a way to bring custom meta data from Previous Order and add to "Order Again"?

I am having a issue when doing "Order Again", with personalize items and when I execute Order Again it do not add the item without personalize items from previous order.

@mastodon072
Copy link

Great !! I was searching for this
WC()->session->set( '_ld_woo_product_data', array() );
Thank You!!

@theboss19065
Copy link

add 'woocommerce_remove_cart_item' hook when user remove item from cart.
add_action( 'woocommerce_remove_cart_item', 'ld_woo_remove_item_data', 10, 1 );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment