-
-
Save RadGH/e3444fc661554a0f8c6f to your computer and use it in GitHub Desktop.
<?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 ); |
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?
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.
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?
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.
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?
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
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
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.
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.
Great !! I was searching for this
WC()->session->set( '_ld_woo_product_data', array() );
Thank You!!
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 );
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: