In Woocommerce I am trying to display the results of order item object and to access it:
$product_meta = $item->get_meta_data();
print_r ($product_meta);
This is what I am trying to pull:
EDIT: This is the output that I get using $item->get_formatted_meta_data( '', true ):
To get all order item meta data, you will use WC_Order_Item get_formatted_meta_data() method with specific arguments, this way:
// Accessible non protected Order item meta data
$item_meta_data = $item->get_formatted_meta_data( '', true );
// Formatted raw Output
echo '<pre>'; print_r($item_meta_data); echo '</pre>';
To access some order item properties, you can use any WC_Order_Item_Product method like:
$item->get_product(); // Get the WC_Product object
$item->get_product_id(); // Get the Product ID
$item->get_variation_id(); // Get the Variation ID
$item->get_name(); // Get the Product name
$item->get_quantity(); // Get the item quantity
// and so on …
Then if you need to access a specific "custom" order item data value, you will use WC_Data get_meta() method:
$custom_value = $item->get_meta("_custom_key");
See: Get Order items and WC_Order_Item_Product in Woocommerce 3
Update (displaying your required custom order item meta data)
The data you need can be accessed and displayed this way:
if( $lessons = $item->get_meta('lessons') ) {
echo '<p>Lessons: '.$lessons.'</p>';
}
if( $tour_guide = $item->get_meta('tour guide') ) {
echo '<p>Tour Guide: '.$tour_guide.'</p>';
}
I hope that this works now.
All I did was put this wc_display_item_meta( $item );
and that is it , it pulls the info automatically !!!!!!!
admin can change those in the edit order screen to anything and they will appear
(thanks to #LoicTheAztec for pointing me to the right direction
Related
I have created product addons for products in my cart. I am associating each product with an image saved to the filesystem, so when you go to view an order you can see the image that was created with the product.
When an image is saved, the cart item gets a custom key. This custom key is used in a cookie to carry the path to the image through the checkout process
if (!function_exists('force_individual_cart_items')) {
function force_individual_cart_items( $cart_item_data, $product_id ){
$unique_cart_item_key = md5( microtime().rand() );
$cart_item_data['unique_key'] = $unique_cart_item_key;
if (isset($_COOKIE['CustomImagePath'])) {// if image path exists that needs to be saved
$imagePath = $_COOKIE['CustomImagePath']; // get image path
$imagePaths = (isset($_COOKIE['ImagePaths']) ? json_decode(stripslashes(html_entity_decode($_COOKIE['ImagePaths'])), true) : array());
$imagePaths[$unique_cart_item_key] = $imagePath; //asscoiate image path with product cart key
setcookie('ImagePaths', json_encode($imagePaths),0,'/'); // save association in image paths cookie
unset($_COOKIE['CustomImagePath']);
setcookie('CustomImagePath', null, -1, '/');
}
return $cart_item_data;
}
}
add_filter( 'woocommerce_add_cart_item_data','force_individual_cart_items', 10, 2 );
When the order is created I then add a new row into the woocommerce_item_meta table with the meta_key of "Custom Image". The issue I am running into is associating the order item with the cart_item_key.
(in the woocommerce_thankyou hook)
global $wpdb, $wp;
$query = "SELECT order_item_id FROM wp_woocommerce_order_items WHERE order_id = $order_id";
$result = $wpdb->get_results($query, true);
$imagePaths = json_decode(stripslashes(html_entity_decode($_COOKIE['ImagePaths'])), true);
foreach ($result as $order_item) {
$item_id = $order_item->order_item_id;
}
$cart_item_custom_key = NOT AVAILABLE IN THE ORDER ITEM
$filePath = $_COOKIE[$cart_item_custom_key];
$wpdb->insert('wp_woocommerce_order_itemmeta', array('order_item_id'=>$post->ID, "meta_key"=>'Custom Image', 'meta_value'=>$filePath))
For example let's say a user selects 3 images. In the cart the first product will have a custom key of 1, the second will have a custom key of 2, and the third a custom key of 3. Using
$woocommerce->cart->get_cart_contents()[cart_item_key]['unique_key'];
I can get that unique key while I have access to the cart. Once the order is created however, order_item does not have that key. Order one, two, and three no longer have custom keys. So I cannot get the image from the cookie with the associated key.
$filePath = $_COOKIE[ ? KEY NO LONGER EXISTS ? ];
$wpdb->insert('wp_woocommerce_order_itemmeta', array('order_item_id'=>$post->ID, "meta_key"=>'Custom Image', 'meta_value'=>$filePath));
is there a way to retrieve the key that that cart item had, because the order item does not seem to have it?
If you just need to get cart item key, save it as custom hidden order item meta data using:
add_action('woocommerce_checkout_create_order_line_item', 'save_cart_item_key_as_custom_order_item_metadata', 10, 4 );
function save_cart_item_key_as_custom_order_item_metadata( $item, $cart_item_key, $values, $order ) {
// Save the cart item key as hidden order item meta data
$item->update_meta_data( '_cart_item_key', $cart_item_key );
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To get this cart item key from the order item you will use something like:
// Get the WC_Order Object from order ID (if needed)
$order = wc_get_order( $order_id );
// Loop though order items
foreach ( $order->get_items() as $item ){
// Get the corresponding cart item key
$cart_item_key = $item->get_meta( '_cart_item_key' );
}
My opinion: You are making things much more complicated than they should be:
Instead of using cookies, you should better use WC_Sessions (if this is really needed). But it should be better to add all required data in hidden input fields on the product page…
You should better set all required data as custom cart item data when the product is added to cart with woocommerce_add_cart_item_data hook (so no need of cookie or something else).
Also you should not use woocommerce_thankyou action hook to add order item custom metadata for many reasons as there is specifically dedicated hooks for that: Once the order is created you can use woocommerce_checkout_create_order_line_item action hook, to save your custom cart item data as order item meta data.
With your provided code I can't help more than that for instance.
I need to update the order item meta in a woocommerce oder on checkout page or while woocommerce creates the order.
I'm using the plugin visual product configurator and it is not passing the right quantity of some items of the order to woocommerce order meta, especially when I use multiple variations on the same product.
Is there a hook for me to use to update the item quantity for a certain order item and how can I use it?
The plugin returns me an array with all the cart information and I can only check if an item of the order appears multiple times - if yes I need to change the quantity of that item to that number in the woocommerce order/database.
I was thinking of adding the following hook to my functions.php
add_action('woocommerce_checkout_create_order', 'change_qty', 1,1);
function change_qty($item_qty){
foreach($item_qty as $qty) {
$qty['product_id'] = $id;
$qty['qty'] = $new_qty
$order->update_meta_data('quantity', $new_qty, $id)
}
}
Whereas $item_qty is be an multi-dimensional array containing the item_ids and adjusted quantities.
Another problem I'm facing is that I dont know when I need to call that function because I get the array from the plugin on the checkout page, but I think WooCommerce has not yet created an order at that moment?
The result should be an adjusted item quantity in the woocommerce order summary in the backend.
To update the order item quantity, you can use WC_Order_Item_Product set_quantity() method.
The correct hook to update order items (line items) is woocommerce_checkout_create_order_line_item action hook, that is triggered during order creation, before data is saved to databased.
add_action('woocommerce_checkout_create_order_line_item', 'change_order_line_item_quantity', 10, 4 );
function change_order_line_item_quantity( $item, $cart_item_key, $cart_item, $order ) {
// Your code goes below
// Get order item quantity
$quantity = $item->get_quantity();
$new_qty = $quantity + 2;
// Update order item quantity
$item->set_quantity( $new_qty );
}
The function arguments (variables) are defined and usable:
$item is the WC_Order_Item_Product Object (not saved yet to database)
$cart_item_key is the related cart item key
$cart_item is the related cart item data
$order is the WC_Order Object (not saved yet to database)
Related:
Get Order items and WC_Order_Item_Product in Woocommerce 3
WC_Order_Item_Product Class and methods API Documentation
WC_Checkout and woocommerce_checkout_create_order_line_item action hook located in the create_order_line_items() method
This can help you (we hook into payment completed notification from the payment provider). If you want to update the _qty just after the order was created, I can change my function. But for now I would update it only when the payment was successful.:
/**
* Update order item qty after payment successful
*/
add_filter( 'woocommerce_payment_complete_order_status', 'update_order_item_qty', 10, 2 );
function update_order_item_qty( $order_status, $order_id ) {
//Get the order and items
$order = new WC_Order( $order_id );
$items = $order->get_items();
//New qty
$new_qty = 0;
foreach ( $items as $item_id => $item_data ) {
update_meta_data( '_qty', $new_qty, $item_id );
}
}
Please try if this is what you'r looking for.
In Woocommerce, I just want to get "local pickup" shipping details to display on a custom email. I tried below functions but they don't show anything for "local pickup".
Which function I can use to get "local pickup" info?
I tried without success the following WC_Order methods:
$order->get_shipping_address_1()
$order->get_formatted_shipping_address()
Edit:
Sorry I did not mention that, but I am using Local Pickup Plus plugin
Edit 2:
This is how I got local pickup info for Local Pickups Plus Plugin docs.woocommerce.com/document/local-pickup-plus which puts meta data to main order variable.
$order = wc_get_order( $order_id );
foreach ($order->get_data() as $key => $value):
if ($key==='shipping_lines'):
foreach ($value as $k=>$v):
$a = $v->get_meta_data();
foreach ($a as $x=>$y):
$t = $y->get_data();
$mykey = $t['key'] ;
$pickup["$mykey"] = $t['value'];
endforeach;
endforeach;
endif;
endforeach;
Then you can use the variables below:
$pickup['_pickup_location_name']
$pickup['_pickup_location_address']['address_1']
$pickup['_pickup_location_phone']['address_2']
$pickup['_pickup_location_address']['postcode']
$pickup['_pickup_location_address']['city']
$pickup['_pickup_location_address']['state'] $pickup['_pickup_location_address']['country']
$pickup['_pickup_location_phone']
$pickup['_pickup_date']
$pickup['_pickup_minimum_hours']
For Order items shipping details refer to: "Get orders shipping method details in WooCommerce 3"
To target order shipping lines details from the WC_Order object you can use the following code:
// Loop though order items shipping
foreach( $order->get_shipping_methods() as $item_id => $item ){
$shipping_item_name = $item->get_name();
$shipping_item_type = $item->get_type();
$shipping_method_title = $item->get_method_title();
$shipping_method_id = $item->get_method_id();
$shipping_method_instance_id = $item->get_instance_id();
$shipping_method_total = $item->get_total();
$shipping_method_total_tax = $item->get_total_tax();
$shipping_method_taxes = $item->get_taxes();
// Get custom meta-data
$formatted_meta_data = $item->get_formatted_meta_data( ' ', true );
// Displaying the row custom meta data Objects (just for testing)
echo '<pre>'; print_r($formatted_meta_data); echo '</pre>';
}
Regarding the custom shipping metadata:
You can access it using the WC_Data method get_meta() from the custom meta "key" located in any custom meta data Objects, like:
$value = $item->get_meta('the_custom_key'); // 'the_custom_key' need to be replaced by the meta "key".
Note: In most Woocommerce email templates and email notification related hooks, you can use the WC_Order object as it's globally included. If not you can get it from the Order ID like:
$order = wc_get_order( $order_id );
Orders related threads:
Get orders shipping method details in WooCommerce 3
Get Order items and WC_Order_Item_Product in Woocommerce 3
How to get WooCommerce order details
Addition - For Local Pickup Plus plugin
It seems that you are using Local Pickup Plus plugin which adds specific custom meta data in the shipping lines.
// Loop though order items shipping
foreach( $order->get_shipping_methods() as $item_id => $item ){
$location_id = $item->get_meta('_pickup_location_id');
$location_name = $item->get_meta('_pickup_location_name');
$location_address = $item->get_meta('_pickup_location_address'); // Array
$location_address_1 = $location_address['address_1'];
$location_address_2 = $location_address['address_2'];
$location_postcode = $location_address['postcode'];
$location_city = $location_address['city'];
$location_state = $location_address['state'];
$location_country = $location_address['country'];
$location_phone = $item->get_meta('_pickup_location_phone');
$pickup_date = $item->get_meta('_pickup_date');
$pickup_min_hours = $item->get_meta('_pickup_minimum_hours');
}
In Woocommerce I am trying to find out how to get the product id for a completed order inside the Customer completed order email template to store it as a PHP variable. This way I will be able to insert it into an external database.
I already tried $product->get_id(); but it does not work.
How can get the Product ID in WooCommerce 3+ from email templates?
You need to loop through Order items… Normally the WC_Order object is defined through the variable $order mostly defined everywhere in email templates.
So the code to get the product ID will be:
// Loop through order items
foreach( $order->get_items() as $item_id => $item ){
// Get the product ID
$product_id = $item->get_product_id();
// Get an instance of the WC_Product object
$product = $item->get_product();
// Get product title (name)
$product_name = $product->get_title(); // or $product->get_name();
// Get product price
$product_price = $product->get_price();
}
See this related thread: Get Order items and WC_Order_Item_Product in Woocommerce 3
With WooCommerce 3+ introducing new API to fetch the order and it's details, a lot of things have changed and many things break as well.
Consider the following code in my plugin:
$order = wc_get_order($order_id);
$id= 27;
var_dump($order->get_item($id));
which gives me bool(false). I have checked the database and the order and the item does exist.
Also
var_dump($order) does return the entire order object with all the items.
So basically, only the function get_item does not seem to work.
The only explanation is that the ID you are using is not an item_id with a type "line_item"…
I have tried and it works normally as expected using WC_Abstract_Order get_item() method when the item_id is of type "line_item".
To get and check the correct "line_item" Item IDs from a defined Order ID, try:
// define an exiting order ID first
$order_id = 422;
$order = wc_get_order($order_id);
foreach($order->get_items() as $item_id => $item_values){
$item_ids_array[] = $item_id;
}
var_dump( $item_ids_array ); // will output all item IDs (of type "line_item") for this order
## ==> Then now you can try (to check get_item() method):
foreach( $item_ids_array as $item_id ){
var_dump( $order->get_item( $item_id ) ); // Will output each WC_Order_Item_Product Object …
}
This should clarify things.
As reference: How to get WooCommerce order details