Woocommerce: get product variation title - php

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;
}

Related

How to get particular product variation quantity dynamically from the cart page in the woocommerce by variation_ID?

I'm trying to display quantity of product variation which added to cart and display this in the loop dynamically.
I'm tried this PHP code:
<?php
$targeted_id = $product->get_id();
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if( in_array( $targeted_id, array( $cart_item['product_id'],$cart_item['variation_id']) )){
$quantity = $cart_item['quantity'];
break; // stop the loop if product is found
}
}
// Displaying the quantity if targeted product is in cart
if( isset( $quantity ) && $quantity > 0 ) {
echo '<a href="http://adel-hat.ru/cart/"><div class="qty_on_product"><i class="tb-icon tb-icon-shopping-cart on_product"></i>';
printf( '<span class="product-cart-items">' . __("%d") . '</span>', $quantity );
echo '</span></div></a>';
}
?>
With this code I'm display all variations added to cart(because here I'm taking parent id) and it works only on page load.
I want to get into $tageted_id variable variation_id dynamically when variation selector changing without page load. How I can do this?
From another hand of my problem I'm trying to get variation_id through jQuery
<script>
jQuery(document).ready(function() {
jQuery( '.variations_form' ).each( function() {
jQuery(this).on( 'found_variation', function( event, variation ) {
console.log(variation);//all details here
var variation_id= variation.variation_id;//selectedvariation
console.log(variation_id);
});
});
});
</script>
And when I use this one i'm getting selected variation ID in console. May be is there any way to send variation_id variable to PHP $tageted_id variable dynamically without page reload?
Now I have update functionality so you can get product selected variation id and use accordingly:
function find_matching_product_variation_id($product_id, $attributes)
{
return (new \WC_Product_Data_Store_CPT())->find_matching_product_variation(
new \WC_Product($product_id),
$attributes
);
}
add_action( 'woocommerce_before_cart', 'woo_find_product_in_cart' );
function woo_find_product_in_cart(){
$targeted_product_variation_ids = array();
$targeted_id = 4215; // product_id
//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'];
$quantity = $cart_item['quantity'];
//first - check if product has variations
if(($targeted_id == $product_id) && (isset($cart_item['variation']) && count($cart_item['variation']) > 0 ))
{
// Cart Product Selected Variation id
$variation_id = find_matching_product_variation_id($product_id,$cart_item['variation']);
//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 $data)
{
$targeted_product_variation_ids[] = $data['variation_id'];
}
}else{
$targeted_product_variation_ids[] = $product_id;
}
if( in_array( $variation_id, $targeted_product_variation_ids) && isset( $quantity ) && $quantity > 0){
echo '<a href="http://adel-hat.ru/cart/"><div class="qty_on_product"><i class="tb-icon tb-icon-shopping-cart on_product"></i>';
printf( '<span class="product-cart-items">Variation Product Qty: ' . __("%d") . '</span>', $quantity );
echo '</span></div></a>';
}
}
}

Get the selected variation attributes from orders in Woocommerce 3

In Woocommerce, I have a report in the admin area that tallies up products sold.There are only 5 products sold on the site but there are 1 or 2 variations on some. The report works great but ignores the variations.
I need to retrieve the attribute value from items ordered to display the data accurately. How do I do this?
get_variation_description() is not working the way I'm applying it.
My code:
$order = wc_get_order( $vs);
//BEGIN NEW RETRIEVE ORDER ITEMS FROM ORDER
foreach( $order->get_items() as $item_id => $item_product ){
$ods = $item_product->get_product_id(); //Get the product ID
$odqty= $item_product->get_quantity(); //Get the product QTY
$item_name = $item_product->get_name(); //Get the product NAME
$item_variation = $item_product->get_variation_description(); //NOT WORKING
}
2020 Update - Handling "Custom Product Attributes" (revamped code)
The WC_Product method get_variation_description() is outdated and deprecated. It's replaced by get_description() method. So you need to get the WC_Product object first.
To get the selected variation attributes, you will use get_variation_attributes( ) method.
// Get an instance of the WC_Order object from an Order ID
$order = wc_get_order( $order_id );
// Loop though order "line items"
foreach( $order->get_items() as $item_id => $item ){
$product_id = $item->get_product_id(); //Get the product ID
$quantity = $item->get_quantity(); //Get the product QTY
$product_name = $item->get_name(); //Get the product NAME
// Get an instance of the WC_Product object (can be a product variation too)
$product = $item->get_product();
// Get the product description (works for product variation too)
$description = $product->get_description();
// Only for product variation
if( $product->is_type('variation') ){
// Get the variation attributes
$variation_attributes = $product->get_variation_attributes();
// Loop through each selected attributes
foreach($variation_attributes as $attribute_taxonomy => $term_slug ){
// Get product attribute name or taxonomy
$taxonomy = str_replace('attribute_', '', $attribute_taxonomy );
// The label name from the product attribute
$attribute_name = wc_attribute_label( $taxonomy, $product );
// The term name (or value) from this attribute
if( taxonomy_exists($taxonomy) ) {
$attribute_value = get_term_by( 'slug', $term_slug, $taxonomy )->name;
} else {
$attribute_value = $term_slug; // For custom product attributes
}
}
}
}
Tested and works for a product variation as all other product types…
It works perfectly to display order item name and attributes key
foreach( $order->get_items() as $order_item_product ) {
$item_meta_data = $order_item_product->get_meta_data();
echo $product_name = $order_item_product->get_name();
echo '<br>';
foreach( $item_meta_data as $meta_data ) {
$meta_data_as_array = $meta_data->get_data();
echo $meta_data_as_array['key'].': '.$meta_data_as_array['value'].'<br>';
}
}
Based on the accepted answer This is so that the typo could be corrected ( i don't have the reputation to do anything else).
notice the $term_slug on the $attribute_value property definition. that is what was missing the $.
// Get an instance of the WC_Order object from an Order ID
$order = wc_get_order( $order_id );
// Loop though order "line items"
foreach( $order->get_items() as $item_id => $item_product ){
$product_id = $item_product->get_product_id(); //Get the product ID
$quantity = $item_product->get_quantity(); //Get the product QTY
$product_name = $item_product->get_name(); //Get the product NAME
// Get an instance of the WC_Product object (can be a product variation too)
$product = $item_product->get_product();
// Get the product description (works for product variation)
$description = $product->get_description();
// Only for product variation
if($product->is_type('variation')){
// Get the variation attributes
$variation_attributes = $product->get_variation_attributes();
// Loop through each selected attributes
foreach($variation_attributes as $attribute_taxonomy => $term_slug){
$taxonomy = str_replace('attribute_', '', $attribute_taxonomy );
// The name of the attribute
$attribute_name = get_taxonomy( $taxonomy )->labels->singular_name;
// The term name (or value) for this attribute
$attribute_value = get_term_by( 'slug', $term_slug, $taxonomy )->name;
}
}
}
For anyone coming across this in the future, I ran into an issue where the last attribute value was not displaying, but when I was looking at orders in the admin it was displaying correctly, so I took a dive into the WooCommerce source code and modified theirs for my needs. You can see their code here if you want to modify it yourself:
\woocommerce\includes\admin\meta-boxes\views\html-order-item-meta.php
Here's what I did to display all keys and values:
$attribute_list = array();
// Start modified code from html-order-item-meta.php
$hidden_order_itemmeta = apply_filters(
'woocommerce_hidden_order_itemmeta',
array(
'_qty',
'_tax_class',
'_product_id',
'_variation_id',
'_line_subtotal',
'_line_subtotal_tax',
'_line_total',
'_line_tax',
'method_id',
'cost',
'_reduced_stock',
'_restock_refunded_items',
)
);
if ($meta_data = $item->get_formatted_meta_data('')) {
foreach ($meta_data as $meta_id => $meta) {
if (in_array($meta->key, $hidden_order_itemmeta, true)) {
continue;
}
$display_key = sanitize_text_field($meta->display_key);
$display_value = sanitize_text_field(force_balance_tags($meta->display_value));
$attribute_list[] = array($display_key => $display_value);
}
}
// End modified code from html-order-item-meta.php
if ($attribute_list) {
$attribute = '';
foreach ($attribute_list as $attributes) {
foreach ($attributes as $attr => $value) {
$attribute .= " - " . $attr . " : " . $value;
}
}
echo $attribute;
}
My code adds each key and value to an array and then loops through to append the key and value to the end of a string with separators. This is what I needed for what I was working on, but it can be easily adapted to fit your needs.

Get SKU of product in cart Wordpress

I'm trying to get the SKU of all the products in my cart.
In the past i tried something similar with the product names. I did it like this:
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names=array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$product_names[]=$_product->post_title;
}
Is there a way like this but instead of the title get the SKU of a product?
EDIT:
I tried Thoby's way like this :
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names=array();
$productsku=array();
foreach($items as $item => $values) {
$_product = $values['data']->post;
$product_names[]=$_product->post_title;
$productsku[]= $_woo_product->get_sku();
}
But i get an error :
Fatal error: Call to undefined method WP_Post::get_sku()
Try :
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$product_names = array();
foreach($items as $item => $values) {
// Retrieve WC_Product object from the product-id:
$_woo_product = wc_get_product( $values['product_id'] );
// Get SKU from the WC_Product object:
$product_names[] = $_woo_product->get_sku();
}
The official WooCommerce API docs: wc_get_product()
I believe this might help you-
$_product->get_sku();
It works with product loops and you can use it inside your cart/checkout/etc..
I assume you already have access to $cart
$cart_items = $cart->get_cart_contents();
$skus = array();
foreach($cart_items as $cart_item) {
// Get WC_Product by Variation ID, if not avaiable use Product ID
$product = wc_get_product($cart_item["variation_id"] ? $cart_item["variation_id"] :
$cart_item["product_id"]);
// Add new SKU to array
array_push($skus, $product->get_sku());
}
The easiest way to get the SKU of a product when you have access to the cart items:
$cart = WC()->cart->get_cart();
foreach( $cart as $cart_item_key => $cart_item ){
$product = $cart_item['data'];
$product->get_sku();
}

Woocommerce: get_formatted_name() of a variation

I'm trying to get the name of a variation in woocommerce, currently im using this:
$variationDetails = wc_get_product($variation_id);
$variationDetails->get_formatted_name();
But get_formatted_name() returns a long string with too many details, I only need the simple name of the variation. I've tried with $variationDetails->get_title() but that returns only the product title instead the variation name.
Is there a simple function to get the variation name?
Hopefully this helps had the same problem recently this is what I wrote to get the variations title for a product
$variations = $product->get_available_variations();
$variation_names = array();
foreach ( $variations as $variation ) {
// Get attribute taxonomies
$taxonomies = array_keys($variation['attributes']);
// Loop through variation taxonomies to get variation name and slug
foreach ($taxonomies as $tax) {
$get_term_tax = str_replace('attribute_', '', $tax);
$meta = get_post_meta( $variation['variation_id'], $tax, true );
$term = get_term_by( 'slug', $meta, $get_term_tax );
$var_name = $term->name;
$variation_names[] = $var_name;
}
}

How to limit item in the cart for each category in woocommerce

Hi I have a visual images,
First click add-to-cart button, check validation of qty allowance for each category, output error message on top of the cart widget.
How do i count product in each cateogy in cart with woocommerce?
Thanks in advance
public function check_product_in_cart($product_in_cart) {
//Check to see if user has product in cart
global $woocommerce;
// start of the loop that fetches the cart items
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
// this is where I started editing Guillaume's code
$cat_ids = array();
foreach ($terms as $term) {
$cat_ids[] = $term->term_id;
}
if(in_array(70, (array)$cat_ids) ||in_array(69, (array)$cat_ids) || in_array(68, (array)$cat_ids)) {
//if exist in "strain" category
//output true
$product_in_cart = true;
//how to count all item in this category??? Thanks
}
}
return $product_in_cart;
}
Here how I got it, count the quantity of the category inside the cart item. First looking if there are any item in the cart belong to that category, if found, get the quantity of that item and output the category count. Work with every single category.
public function check_product_in_cart($product_in_cart) {
//Check to see if user has product in cart
global $woocommerce;
// start of the loop that fetches the cart items
$aty = 0;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
// this is where I started editing Guillaume's code
$cat_ids = array();
foreach ($terms as $term) {
$cat_ids[] = $term->term_id;
}
if(in_array(70, (array)$cat_ids) ||in_array(69, (array)$cat_ids) || in_array(68, (array)$cat_ids)) {//popular
//category is in cart!
$product_in_cart = true;
$product_catqty = $values['quantity'];//get the quantiy of the item
$aty += $product_catqty;
}
$cat_qty = $aty;
}
return $cat_qty;
}

Categories