How to Get Product Name in Order Meta [duplicate] - php

This question already has answers here:
Get Order items and WC_Order_Item_Product in WooCommerce 3
(2 answers)
Access and display order item meta data in Woocommerce
(2 answers)
Woocommerce - Getting the order item price and quantity.
(3 answers)
Closed 3 years ago.
I am trying to add the product name to the sku when the sku is empty using the following method. So far this works but the last thing is, how do I call the product name within this code?
add_action( 'woocommerce_add_order_item_meta', 'so_28193771', 10, 3 );
function so_28193771( $item_id, $values, $cart_item_key ) {
$item_sku .= get_post_meta( $values[ 'product_id' ], '_sku', true );
if ( empty( $item_sku ) ) {
wc_add_order_item_meta( $item_id, 'sku', $item_sku , false );
}
}

Use the below code inside your function.
WooCommerce 3.0+
Get Product id from order id in Woocommerce
$order = wc_get_order( $order_id );
$items = $order->get_items();
Then if you loop through the items, you can get all the relevant data:
foreach ( $items as $item ) {
$product_name = $item->get_name();
$product_id = $item->get_product_id();
$product_variation_id = $item->get_variation_id();
}
Pre-WooCommerce 3.0
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
}

Related

Can't write to ACF custom field in a WooCommerce order

I can't write a value to an ACF custom field on a WooCommerce order. I can read the same field. How can I update this ACF field on the order?
// autocomplete virtual order + set backorder flag
add_action('woocommerce_order_status_changed', 'ke_set_backorder_flag');
function ke_set_backorder_flag($order_id)
{
if ( ! $order_id ) {
return;
}
global $product;
//get an instance of the WC_order object
$order = wc_get_order( $order_id );
// loop to get the order items from WC_Order_Item_Product objects
foreach( $order->get_items() as $item_id => $item ) {
//only look at line items (products)
if ( $item['type'] == 'line_item' ) {
$_product = $item->get_product();
$ke_stock_qty = $_product->get_stock_quantity();
//check if backorder
if ( $ke_stock_qty < 1 ) {
// TEST dst - read ke_stock ACF custom field
$field_key='field_604a3d0d86088';
$ke_stock_value = get_field( $field_key );
// TEST write the actual stock qty in ke_stock
update_field( $field_key, $ke_stock_qty );
}
}
}
}
My goal eventually is to set a boolean field as a backorder flag which I can show in the order view. But for now I'm just trying to update a text field.
Any help is much appreciated.

Limit WooCommerce products in cart only from one custom taxonomy

I'm trying to restrict customers on my Woocommerce store to only be allowed to order products from 1 "supplier" at a time. I am defining the "Supplier" by a custom taxonomy called "supplier". The code I am trying is just restricting everything for some reason.
function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
// If passed
if ( $passed ) {
// If cart is NOT empty when a product is added
if ( !WC()->cart->is_empty() ) {
// Set vars
$current_product_tag_ids = array();
$in_cart_product_tag_ids = array();
// Get current product categories via product_id
$current_product_tag_ids = wc_get_product_term_ids( $product_id, 'supplier' );
// Loop through cart items checking for product categories
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Get product categories from product in cart via cart item product id
$in_cart_product_tag_ids = array_merge( $in_cart_product_tag_ids, wc_get_product_term_ids( $cart_item['product_id'], 'product_cat' ) );
}
// Removes duplicate values
$in_cart_product_tag_ids = array_unique( $in_cart_product_tag_ids, SORT_NUMERIC );
// Compare
$compare = array_diff( $current_product_tag_ids, $in_cart_product_tag_ids );
// Result is NOT empty
if ( !empty ( $compare ) ) {
wc_add_notice( 'This product is with a different supplier. Please only order from 1 supplier at a time.', 'error' );
$passed = false;
}
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );
I'm not trying to limit it to 1 product per supplier, I'm trying to restrict them so they can only order products from 1 supplier per order. Once they've added a product to their basket from the supplier "Supplier 1" for example, they then won't be able to add a product from any other supplier other than "Supplier 1".
I made a previous post trying to use categories instead of a custom taxonomy but I need them to be separate so we're not limited on categories. This post can be found here: One Category Per Order Woocomerce
The following will allow adding to cart items from one "supplier" only:
add_filter( 'woocommerce_add_to_cart_validation', 'only_one_supplier_by_order', 10, 2 );
function only_one_supplier_by_order( $passed, $product_id ) {
if ( WC()->cart->is_empty() )
return $passed;
$taxonomy = 'supplier';
$term_ids = wp_get_post_terms( $product_id, $taxonomy, ['fields' => 'ids']);
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if( ! has_term( $term_ids, $taxonomy, $cart_item['product_id'] ) ) {
// Displaying a custom notice
wc_add_notice( __('This product is with a different supplier. Please only order from 1 supplier at a time.'), 'error' );
return false; // Avoid add to cart
}
}
return $passed;
}
Now to be sure that customer can't checkout with different suppliers in cart, you can add this:
// To be sure (avoiding checkout)
add_action( 'woocommerce_check_cart_items', 'only_one_supplier_by_order_check' );
function only_one_supplier_by_order_check() {
$taxonomy = 'supplier';
$term_names = []; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
$terms = wp_get_post_terms( $cart_item['product_id'], $taxonomy );
if( ! empty($terms) ) {
$term = reset($terms);
$term_names[$term->term_id] = $term->name;
}
}
// Allow only one supplier in cart (avoid checkout for more than one
if( count( $term_names ) > 1 ) {
// Displaying a custom notice
wc_add_notice( __('Only items from one supplier at the time are allowed in cart'), 'error' );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Product attribute empty value from order item in Woocommerce 3

I know that there are a lot of questions already for that matter but im not able to figure out how to get a custom product attribute from an woocommerce order. here is what i have try:
$order = wc_get_order( $order_id );
$order_data = $order->get_data();
foreach ($order->get_items() as $item_key => $item_values) {
$product = $item_values->get_product(); // Get the product
$product_id = $item_values->get_product_id(); // the Product id
$tokens = get_post_meta($product_id, 'Tokens', true);
}
I have also try:
$tokens = $product->get_attribute( 'Tokens' );
and
$tokens = array_shift( wc_get_product_terms( $product_id, 'Tokens', array( 'fields' => 'names' ) ) );
My custom product attribute has the name "Tokens" and the value 5000 but im getting an empty return,
what am i doing wrong?
That can happen for a variable product when the product attribute is not set as an attribute for variations.
So when you have a product variation as order item, you need to get the parent variable product to get your product attribute value (if this product attribute is not set as an attribute for variations).
If it is the case for "Tokens" product attribute, try the following:
$attribute = 'Tokens';
$order = wc_get_order( 857 );
// Loop through order line items
foreach ( $order->get_items() as $item_id => $item ) {
$product = $item->get_product(); // Get the WC_Product object
// For Product Variation type
if( $item->get_variation_id() > 0 ){
$parent = wc_get_product($product->get_parent_id());
$term_names = $parent->get_attribute($attribute);
}
// For other Product types
else {
$term_names = $product->get_attribute($attribute);
}
// Testing display (the string of coma separated term names if many)
if( ! empty( $term_name ) )
echo '<p>'.$term_name.'</p>';
}
Tested and works in Woocommerce 3+

Add woocommerce variation meta data to order

I'm creating a Woocommerce webshop for a client who is selling different types of breakfasts. Each breakfast has several variations based on the amount of persons.
For example:
Breakfast x (product)
- 1 person (variation)
- 2 persons (variation)
- 3 persons (variation)
- 4 persons (variation)
Each variation contains (different) meta data.
Basically the meta data contains the articles needed to create a breakfast and needs to be added to the order line items in woocommerce when an order is created. The composition of the meta data is different for each variation.
Now I'm able to add meta data to the order item, but somehow meta data gets mixed up when adding two or more products.
Below is my code and output in Woocommerce.
When I use the function just to print the variation meta data instead of adding it to the woocommerce order, I can see that the meta data is correct and the most inner for loop is executed one variation after another. I don't know if wc_add_order_item_meta is causing an issue or maybe the hook I'm calling.
function oc_line_item_metadata( $item_id, $item, $order_id ) {
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ($items as $item) {
$variation_id = $item['variation_id'];
$product_variation = new WC_Product_Variation( $variation_id );
$meta_data = $product_variation->get_meta_data();
for ($i=0; $i < count($meta_data); $i++) {
$article = ($meta_data[$i]->get_data());
$article_id = $article['id'];
$article_key = $article['key'];
$article_value = $article['value'];
wc_add_order_item_meta( $item_id, $article_key, $article_value );
}
}
}
add_action( 'woocommerce_new_order_item', 'oc_line_item_metadata', 10, 3 );
You can find the output via this link:
https://image.ibb.co/mtsnrb/order.png
Yesterday I found some more information that helped me solve the issue. It seems I'm not using the correct method to get the order_id and variation_id.
Below the correct code that solved my issue:
function oc_line_item_metadata( $item_id, $item, $order_id ) {
$order = wc_get_order( $order_id );
foreach ($order->get_items() as $item_id => $item_obj) {
$variation_id = $item_obj->get_variation_id();
}
$product_variation = new WC_Product_Variation( $variation_id );
$meta_data = $product_variation->get_meta_data();
for ($i=0; $i < count($meta_data); $i++) {
$article = ($meta_data[$i]->get_data());
$article_id = $article['id'];
$article_key = $article['key'];
$article_value = $article['value'];
wc_add_order_item_meta( $item_id, $article_key, $article_value );
}
}

Change SKU number of product for returning clients in thankyou hook

In WooCommerce, I am trying to change a product SKU of an order received by a returning client.
Currently I use the current code but it does not seem to work.
I have 2 different products. The product with id 5836 is a normal product while the other is a subscription.
This is my code:
function action_woocommerce_thankyou( $order_id ) {
// Let's get the order details
$order = wc_get_order( $order_id );
// Customer who made the purchase
$user_id = $order->get_user_id();
// Now get order count for the customer
$order_count = wc_get_customer_order_count( $user_id );
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
if ( $order_count > 1) {
// Returning customer...
if ( $product_id == '5836') {
update_post_meta( $order_id['product_id'], '_sku', $ANT0001 );}
else {
// Returning customer...
update_post_meta( $order_id['product_id'], '_sku', $ANT0002 );}
} else {
// New customer...
}
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
Update (related to your comment): First concerning SKU(s) item(s) in the order, is not possible to update the SKU in the order, as there is no related data for any item ID concerning SKU in the related database table wp_woocommerce_order_itemmeta. The related SKU(s) data is taken from product(s) directly.
I have tested your code and it works globally.
what that doesn't work is:
update_post_meta( $order_id['product_id'], '_sku', $ANT0001 );
// and
update_post_meta( $order_id['product_id'], '_sku', $ANT0001 );
because you are using undefined variables $ANT0001 and $ANT0002. Instead you should use this:
update_post_meta( $product_id, '_sku', 'ANT0001' );
// and
update_post_meta( $product_id, '_sku', 'ANT0001' );
or you should define your 2 variables $ANT0001 and $ANT0002, and it will work, just as expected.
Don't forget that normally sku reference number has to be unique for each product.

Categories