Woocommerce: get_formatted_name() of a variation - php

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

Related

WooCommerce get custom field from attributte

Is it possible to get custom field from product attribute?
And can be connected by variation or product id?
I tried this one:
function color_in_loop(){
global $product;
//Getting product attributes
$attributes = $product->get_attributes();
$values = wc_get_product_terms( $product->id, 'pa_color', array( 'fields' => 'all' ) );
foreach ( $values as $term ) {
$icon = get_term_meta('product_attribute_color', 'pa_color_'.$term->term_id);
echo $icon['url'];
}
}
add_action('woocommerce_after_shop_loop_item', 'color_in_loop');
Your get_term_meta is wrong, and there is no need to use
$attributes = $product->get_attributes();
You can achieve what you are looking for simply with the get_the_terms method since you know the specific attribute you need the icon for.
function color_in_loop(){
global $product;
//Getting product attributes
$product_id = $product->get_id();
$colors = get_the_terms($product_id, 'pa_color');
foreach ( $colors as $color ) {
$icon = get_term_meta($color->term_id,'product_attribute_color',true);
echo $icon['url'];
}
}
add_action('woocommerce_after_shop_loop_item', 'color_in_loop');
It is not tested but it should work

Showing all prices for variable products listed instead of range of prices

Is there any way to replace range price of variable products in woocommerce on shop page and instead of it showing a list of variations and their prices per product in order to display variations to customer and showing 'Add to Cart' for all type of products not 'Choose an Option' for variable products.
I have tested a lot of code snippets without success.
Below code is the closest to what I need, I used code suggested here Get specific product attribute name and value for each WooCommerce variation of a variable product and changed it. but still the problem is that part of attribute is not shown.
add_filter( 'woocommerce_variable_price_html', 'custom_variable_price_html', 10, 2 );
function custom_variable_price_html( $price, $product ) {
if(!is_admin()){
if(is_shop()){
$product_attribute_slug = 'ابعاد-فرش';
$targeted_taxonomy = 'pa_' . $product_attribute_slug;
$available_variations = $product->get_available_variations();
$output = '<div>';
foreach( $available_variations as $variation_data ){
if( $variation_data['display_price'] === $variation_data['display_regular_price'] ) {
$price_to_display = wc_price( $variation_data['display_price'] );
} else {
$variation = wc_get_product($variation_data['variation_id']); // Get the WC_Product_Variation Object
$price_to_display = wc_get_price_to_display( $variation, array('price' => $variation->get_sale_price() ) );
}
foreach ( $variation_data['attributes'] as $variation_attribute => $term_slug ) {
// Get the taxonomy slug
$taxonomy = str_replace( 'attribute_', '', $variation_attribute );
// Get the correct product attribute term value for this variation
if( $taxonomy === $targeted_taxonomy ) {
// Get the attribute value term name
$term_name = get_term_by( 'slug', $term_slug, $taxonomy )->name;
}
}
$output .= '<span>' . $term_name . ':' . wc_attribute_label( $targeted_taxonomy ) . ':' . strip_tags($price_to_display) . '</span><br>';
}
$output .= '</div>';
$price = $output;
return $price;
} else {
return $price;
}
} else {
return $price;
}
}
what I get is:
but I need something Like this:
As I noticed
$term_name
variable in code is empty.
Any help is appreciated.
Solution: set taxonomy as follow and use it in get_term_by() function:
$taxonomy = 'pa_ابعاد-فرش';

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.

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

Improve WC_Product_Query on Woocommerce products with variations

I've written a function to loop through all products, finding variations that are out of stock and then deleting the variation and the variable products associated attributes so that any product filter plugins do not show specific variations when they are out of stock.
My function works fine on my test site but I'm looking for some advice on making this more efficient as I have some concerns about running it on a live site which has hundreds of products with around 15 variations per product.
Here's my function code:
function wpmad_purge_variations_not_in_stock(){
echo 'Purging products...<br><br>';
$args = array( 'status' => 'publish', 'limit' => -1 );
$products = wc_get_products( $args );
foreach ( $products as $product ){
if ( $product->is_type( 'variable' ) ){
$product_id = $product->id;
// Get all available product variations for current product/item
$variations = $product->get_available_variations();
// Loop through each of the available variations
foreach ( $variations as $variation ){
// Check if variation is no longer in stock
if ( $variation['is_in_stock'] == '' ){
$variation_id = $variation['variation_id'];
// Attribute counter
$count = 1;
// For each variation attribute
foreach ( $variation['attributes'] as $att_name => $att_value ){
$atts[$count]['name'] = str_replace( 'attribute_', '', $att_name );
$atts[$count]['value'] = $att_value;
$count++; // Increase counter for each loop
}
// Delete product variation post
echo 'Deleted product variation ID #' . $variation_id . '<br>';
wp_delete_post( $variation_id, true );
// For each attribute
foreach ( $atts as $att ){
// Remove attribute from main product
echo 'Deleted product attribute (' . $att['name'] . ' - ' . $att['value'] . ') for product ID #' . $product_id . '<br><br>';
wp_remove_object_terms( $product_id, $att['value'], $att['name'] );
}
}
}
}
}
echo 'Product variations have now been purged if out of stock';
}
Is it possible to use the function wc_get_products() to only return variable products and are there any efficiency/peformance improvements that can be made to my code?
With the WC_Product_Query when using wc_get_products() you can use the "type" argument to target only variable products like:
$products = wc_get_products( array( 'status' => 'publish', 'limit' => -1, 'type' => 'variable' ) );
This will improve the efficiency / performance of your code.
Note: The $atts variable should be initialized just after the 2nd foreach loop like: $atts = array();

Categories