Update custom order item meta in WooCommerce - php

I am missing something. I have seen several articles about how to update an items meta data but I can't get any one of them to work. I need to get the item_id but I can't figure out how to do that.
$your_phone = $item->get_meta('dinner_phone'); // 1115559999
$update_phone = wdc_format_phone($your_phone); // comes back (111) 555-9999
wc_update_order_item_meta($item_id,'dinner_phone', $update_phone); //I want to update with new format
$new_phone = $item->get_meta('dinner_phone'); // doesn't work I still get 1115559999
I have tried to pull the Item_id by the following
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
$item_id = $item['item_id'];
break;
}
Also tried this
foreach ($items as $key => $product ) {
$item_id = $key;
}

You will use the following from an existing WC_Order Object $order variable:
foreach ( $order->get_items() as $item-id => $item ) {
$dinner_phone = $item->get_meta('dinner_phone'); // 1115559999
if ( ! empty( $dinner_phone ) ) {
$formatted_diner_phone = wdc_format_phone( $dinner_phone ); // comes back (111) 555-9999
$item->update_meta_data('dinner_phone', $formatted_diner_phone);
$item->save(); // Save item
$new_phone = $item->get_meta('dinner_phone');
echo $new_phone; // Check that items is updated
}
$order->calculate_totals(); // Recalculate Order totals and save
}
It should work.

Related

How to get the prodcut size attribute that the customer selected after the checkout WC

I have 2 attributions for color and size of t-shirt, I want to get the values that user selected after he creates the order
So when I check the data of the created order I don't find the related attribute of the product that the customer selected at all (btw I check through woocommerce_process_shop_order_meta hook )
function getcartitems($order_id)
$order = wc_get_order($order_id);
$order_data = $order->get_data(); // The Order data
$items = $order->get_items();
}
// the hook will be changed to woocommerce_checkout_order_processed
add_action('woocommerce_process_shop_order_meta', 'getcartitems');
I'm not sure what you want to do with the selected data, but here is how you wuld grab the values.
function getcartitems($order_id) {
// Get an instance of the WC_Order object
$order = new WC_Order( $order_id );
// Get the items in the order
$items = $order->get_items();
foreach ( $items as $item ) {
// Get the product ID
$product_id = $item['product_id'];
// Get the product object
$product = wc_get_product( $product_id );
// Get the product attribute values
$attributes = $product->get_attributes();
foreach ( $attributes as $attribute ) {
// Get the attribute name
$attribute_name = $attribute['name'];
// Get the attribute value(s)
$attribute_values = $item['variation'][ "attribute_{$attribute['name']}" ];
// Output the attribute name and value(s)
echo "Attribute name: {$attribute_name} <br>";
echo "Attribute values: {$attribute_values} <br>";
}
}
}
// the hook will be changed to woocommerce_checkout_order_processed
add_action('woocommerce_process_shop_order_meta', 'getcartitems');

Woocommerce : Generate a unique key per item and send it in the order email

I would like that when a user orders items, a special unique key is generated for each item. These keys / This key should then be visible in ALL order mails (admin and customer). Here is what I tried to do after some research around the web :
add_action('woocommerce_order_status_processing', 'process_membership_order');
//Trying to generate my keys for each item
function process_membership_order($order_id) {
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach ($items as $item_id => $product) {
$key_id = "TESTING123"; //testing purpose of course, will call a function later
wc_add_order_item_meta($item_id, 'custom_key', $key_id);
}
}
add_action( 'woocommerce_email_order_meta', 'add_email_order_meta', 10, 3 );
//Trying to edit the email order infos
function add_email_order_meta($order_obj, $sent_to_admin, $plain_text){
$key = get_post_meta( $order_obj->get_order_number(), 'custom_key', true );
if ( $plain_text === false ) {
echo "<h2>Custom Information</h2><p>$key</p>";
} else {
echo "CUSTOM INFORMATION : $key";
}
}
It doesn't seem to work, my mails have the new title but it's always empty instead of showing my TESTING123 as many times as there is an item. I'm more a tinkerer than a dev, I've used an entire day on this, a little push on the right direction would be really appreciated, I think I'm close but something's missing ! Anyway, any advice would be great, thank you.
I think you need to get order items from the order object and then you can get your custom meta by using wc_get_order_item_meta. check below code.
add_action('woocommerce_order_status_processing', 'process_membership_order');
//Trying to generate my keys for each item
function process_membership_order($order_id) {
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach ($items as $item_id => $product) {
$key_id = "TESTING123"; //testing purpose of course, will call a function later
wc_add_order_item_meta($item_id, 'custom_key', $key_id);
}
}
add_action( 'woocommerce_email_order_meta', 'add_email_order_meta', 10, 3 );
//Trying to edit the email order infos
function add_email_order_meta($order_obj, $sent_to_admin, $plain_text){
$order = wc_get_order( $order_obj->get_order_number() );
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item ) {
$key = wc_get_order_item_meta( $item_id, 'custom_key', true );
if ( $plain_text === false ) {
echo "<h2>Custom Information</h2><p>$key</p>";
} else {
echo "CUSTOM INFORMATION : $key";
}
}
}

How to get order items ids to get some product meta data?

I'm trying to extract item meta value from Woocommerce's orders by using:
$data = wc_get_order_item_meta( $item, '_tmcartepo_data', true );
However, I can't find a way to get order_item_id as the first parameter (using get_items)
global $woocommerce, $post, $wpdb;
$order = new WC_Order($post->ID);
$items = $order->get_items();
foreach ( $items as $item ) {
$item_id = $item['order_item_id']; //???
$data = wc_get_order_item_meta( $item_id, '_tmcartepo_data', true );
$a = $data[0]['value'];
$b = $data[1]['value'];
echo $a;
echo $b;
}
And I mean this order item_id (1 and 2)
Order_item_id in database - Image
How can I don that?
Thanks.
2018 Update:
Clarifying the answer with 2 possible cases
Added compatibility for woocommerce 3+
So There can be 2 cases:
1) Get product meta data (not set in order item meta data):
You will need to get the product ID in the foreach loop for a WC_Order and to get some metadata for this product you wil use get_post_meta() function ( but NOT wc_get_order_item_meta() ).
So here is your code:
global $post;
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach ( $order->get_items() => $item ) {
// Compatibility for woocommerce 3+
$product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $item['product_id'] : $item->get_product_id();
// Here you get your data
$custom_field = get_post_meta( $product_id, '_tmcartepo_data', true);
// To test data output (uncomment the line below)
// print_r($custom_field);
// If it is an array of values
if( is_array( $custom_field ) ){
echo implode( '<br>', $custom_field ); // one value displayed by line
}
// just one value (a string)
else {
echo $custom_field;
}
}
2) Get order item meta data (custom field value):
global $post;
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item ) {
// Here you get your data
$custom_field = wc_get_order_item_meta( $item_id, '_tmcartepo_data', true );
// To test data output (uncomment the line below)
// print_r($custom_field);
// If it is an array of values
if( is_array( $custom_field ) ){
echo implode( '<br>', $custom_field ); // one value displayed by line
}
// just one value (a string)
else {
echo $custom_field;
}
}
If the custom field data is an array, you can access the data in a foreach loop:
// Iterating in an array of keys/values
foreach( $custom_field as $key => $value ){
echo '<p>key: '.$key.' | value: '.$value.'</p>';
}
All code is tested and works.
Reference related to data in orders:
How to get WooCommerce order details (also for woocommerce 3)
Get Order items and WC_Order_Item_Product in Woocommerce 3
When doing the foreach on $order->get_items(), their key is actually the orderline ID. So:
foreach ( $order->get_items() as $key => $item ) {
$data = wc_get_order_item_meta( $key, '_tmcartepo_data' );
...
}
Late to the party, but being working with the same point with TM Extra Product Options plugin, I think this is what answers your question:
$order = wc_get_order( $post->ID );
$items = $order->get_items();
foreach( $items as $item ){
$data = unserialize($item['item_meta']['_tmcartepo_data'][0]);
$a = $data[0]['value'];
$b = $data[1]['value'];
echo $a;
echo $b;
}
Tested and works in my case.
Use this <pre><?php print_r($items); ?></pre> to check all the contents of the $items array/object.
foreach ( $order->get_items() as $key => $item ) {
$data = wc_get_order_item_meta( $key, '_tmcartepo_data' );
...
This solution was worth to me, change "_tmcartepo_data" for your meta_key.
A simple way to get order items from database;
/**
* #param $order_id
*
* #return array|null|object
*/
function get_order_items( $order_id ) {
global $wpdb, $table_prefix;
$items = $wpdb->get_results( "SELECT * FROM `{$table_prefix}woocommerce_order_items` WHERE `order_id` = {$order_id}" );
$item_name = array();
foreach ( $items as $item ) {
$item_name[] = $item->order_item_name;
}
return $item_name;
}

How to get categories from an order at checkout in WooCommerce?

I am want to get the category of the items in the cart at the checkout in WooCommerce. I want to extract it and then place it in a field in my custom checkout.
I'm using WooCommerce MultiStep Checkout Wizard premium plugin and a specific hook:
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep');
I'm a little lost and can't find much documentation for what I need to use to get it.
I'm trying to just get items to appear but I just get an empty array.
$order = new WC_Order( $order_id );
$items = $order->get_items();
var_dump($items);
You could try first with your approach "new WC_Order( $order_id );", this way:
function destinationStep( $order_id )
global $woocommerce;
$order = new WC_Order( $order_id );
$items = $order->get_items();
// echo var_dump($items);
//----
foreach ($items as $key => $item) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$terms = get_the_terms( $product_id, 'product_cat' );
// echo var_dump($terms);
foreach ( $terms as $term ) {
// Categories by slug
$product_cat_slug= $term->slug;
}
}
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep', 10, 1);
If it still doesn't work try with "new WC_Order($post->ID)" approach:
function destinationStep()
global $woocommerce, $post;
$order = new WC_Order($post->ID);
$items = $order->get_items();
// echo var_dump($items);
//----
foreach ($items as $key => $item) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$terms = get_the_terms( $product_id, 'product_cat' );
// echo var_dump($terms);
foreach ( $terms as $term ) {
// Categories by slug
$product_cat_slug= $term->slug;
}
}
add_action('woocommerce_multistep_checkout_before_order_info', 'destinationStep');
Update - After some thought:
You can't get the order Id for `'post_type' => 'shop_order', because it doesn't exist yet. This order ID is generated when customer submit the order, but not before on checkout page.
So in this case, it's normal to get an empty array.

Woocommerce: get product variation title

I'm writing a plugin and cannot get the correct variation title
In Woocommerce the variation i use is called "unfolded laminated". but when i try to get the title of a variation i get: "Variation #781 of Chart"
This is the code is use:
foreach ($order->get_items() as $item) {
$product_variation_id = $item['variation_id'];
if ($product_variation_id)
{
$product = new WC_Product($product_variation_id);
$productname = get_item_variations($product_variation_id);
}
else
{
$product = new WC_Product($item['product_id']);
$productname = get_the_title($item['product_id']);
}
}
How do i get the correct title?
I was actually looking this up trying to figure it out and here's my solution because the variation title was returning a slug.
Tested on WC 2.4.13
$variation = new WC_Product_Variation($variation_id);
$title_slug = current($variation->get_variation_attributes());
$results = $wpdb->get_results("SELECT * FROM wp_terms WHERE slug = '{$title_slug}'", ARRAY_A);
$variation_title = $results[0]['name'];
I stumbled across this just now looking for a 'quick' fix. Since no-one has posted an answer I thought I would.
I just used WordPress get_post_meta to fetch attribute_options. This is where all the option titles are stored (variation titles are product options).
$product_options = get_post_meta($item['variation_id'], 'attribute_options');
Will return an array
[attribute_options] => Array
(
[0] => Some Variation Title
)
Here is a solution for this problem which is tested with WooCommerce 3.2.6
//Loop through each item from the cart
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
//get the current product ID
$product_id = $cart_item['product_id'];
//first - check if product has variations
if(isset($cart_item['variation']) && count($cart_item['variation']) > 0 ){
//get the WooCommerce Product object by product ID
$current_product = new WC_Product_Variable($product_id);
//get the variations of this product
$variations = $current_product->get_available_variations();
//Loop through each variation to get its title
foreach($variations as $index => $data){
get_the_title($data['variation_id']);
}
}
}
In this function to return the title of the input variation, you can change the delimiter ', ' to a space or whatever is needed.
function get_variation_title($variation) {
$str_name = '';
$arr_attributes = $variation -> get_variation_attributes(FALSE);
if (is_array($arr_attributes)) {
foreach($arr_attributes as $attribute_slug=> $variation_slug) {
$term = get_term_by('slug', $variation_slug, $attribute_slug);
if (isset($term)) {
if (strlen($str_name) > 0) $str_name.= ', ';
$str_name.= $term -> name;
}
}
}
return $str_name;
}

Categories