Reputation: 1437
I would like to display the default product attributes form value and it's regular price in my front end template file.
The var_dump
below shows options in an array. I Need to get the [default_attributes]
values.
<?php
global $product;
echo var_dump( $product );
// Need to get the [default_attributes] values
?>
Upvotes: 10
Views: 14868
Reputation: 643
<?php
/**
* Get default product variation
*
* note: this method check for exact match.
*
* @param mixed $product_id WC_Product|WP_Post|int|bool $product Product instance, post instance, numeric or false to use global $post.
* @param string $return Optional. The format to return the results in. Can be 'id' to return id of variation or 'object' for the product variation object. Default 'id'.
*
* @return int|WC_Product_Variation return 0 if not found.
*/
function wc_get_default_variation( $product_id = false, $return = 'id' ) {
// do not use wc_get_product() to bypass some limits
$product = WC()->product_factory->get_product( $product_id );
if ( empty( $product ) || ! $product instanceof WC_Product_Variable ) {
return 0;
}
if ( $product->has_child() ) {
$attributes = $product->get_default_attributes();
if ( ! empty( $attributes ) ) {
$check_count = true;
$attributes_count = count( $attributes );
// get in-stock (if enabled in wc options) and visible variations
$variations = $product->get_available_variations( 'objects' );
foreach ( $variations as $variation ) {
$variation_attributes = $variation->get_attributes();
// check count for first time
// if not match, it means that user do not set default value for some variation attrs
if ( $check_count && $attributes_count !== count( $variation_attributes ) ) {
break;
}
// no need to check count anymore
$check_count = false;
// remove 'any' attrs (empty values)
$variation_attributes = array_filter( $variation_attributes );
// add 'any' attrs with default value
$variation_attributes = wp_parse_args( $variation_attributes, $attributes );
// check is default
if ( $variation_attributes == $attributes ) {
if ( $return === 'id' ) {
return $variation->get_id();
}
return $variation;
}
}
}
}
return 0;
}
https://gist.github.com/AkramiPro/c8ddb83d253714730ac26d3a64e7941e
Upvotes: 0
Reputation: 2395
You can also use get_matching_variation
function.
function getDefaultVariation($product) {
$defaultAttributes = $product->get_default_attributes();
$formattedAttributes = [];
foreach ($defaultAttributes as $taxonomy => $value) {
$formattedAttributes["attribute_{$taxonomy}"] = $value;
}
$variationID = $product->get_matching_variation($formattedAttributes);
// Output the default variation ID
print_r($variationID);
}
To get the full data of the default selected variation, you can call the WC_Product_Variation
class and pass the variation ID. Here is the full implementation.
function getDefaultVariation($product) {
$defaultAttributes = $product->get_default_attributes();
$formattedAttributes = [];
foreach ($defaultAttributes as $taxonomy => $value) {
$formattedAttributes["attribute_{$taxonomy}"] = $value;
}
$variationID = $product->get_matching_variation($formattedAttributes);
if(!$variationID) {
return;
}
$variation = new WC_Product_Variation($variationID);
// Output the full data of the given variationID
print_r($variation);
}
Upvotes: 0
Reputation: 554
WC_Product_Data_Store_Interface
offers a way to get a product variation matching a list of attributes for a variable WC_Product with ->find_matching_product_variation() :
function get_product_default_variation( $WC_Product ) {
$default_attributes = $WC_Product->get_default_attributes();
// ->find_matching_product_variation() needs term slugs of matching
// attributes array to be prefixed with 'attribute_'
$prefixed_slugs = array_map( function( $pa_name ) {
return 'attribute_'. $pa_name;
}, array_keys( $default_attributes ) );
$default_attributes = array_combine( $prefixed_slugs, $default_attributes );
$default_variation_id = ( new \WC_Product_Data_Store_CPT() )->find_matching_product_variation( $WC_Product, $default_attributes );
return wc_get_product( $default_variation_id );
}
Upvotes: 2
Reputation: 197
I found this question while looking for a simpler way to do it than I was, perhaps a built in WooCommerce function, but for now we still need to find it ourselves.
I did this a little bit differently, and by using microtime to test its performance on my hardware, it runs in about 1/2000 of the time. Here is my code:
function setDefaultVariation(): array {
global $product;
$all_variations = $product->get_available_variations();
$default_attributes = $product->get_default_attributes();
if (empty($default_attributes))
return $all_variations[0];
$default_variation_key = -1;
foreach ($all_variations as $variation) {
$default_variation_key++;
//Check if variation has more or less assigned attributes than the default.
if (getAssignedAttributeCount($variation['attributes']) !== count($default_attributes))
continue;
$is_default = 0; //This will count how many attributes match the default values
//We check each default attribute term and value to see if it matches the term-value pairs of the current variation. Some might have multiple pairs, so we use a counter to know if all are matched
foreach ($default_attributes as $default_term => $default_value) {
if($variation['attributes']['attribute_' . $default_term] !== $default_value) {
break; //A attribute value does not match so this one cant be default, break.
}else{
$is_default++;
if ($is_default === count($default_attributes) ) { //All default attributes matches this variation
return $all_variations[$default_variation_key];
}
}
}
}
return $all_variations[0];//If this statement is reached, no default variation was found, so return key of first variation
}
function getAssignedAttributeCount($attributes): int {
$count = 0;
foreach ($attributes as $attribute) {
if ($attribute !== '')
$count++;
}
return $count;
}
The code finds the default attributes for a product, then loops through each variation to check if the variation's attributes matches the default attributes.
It supports products that have multiple attributes, and also checks that the variation has the exact attributes by comparing the number of attributes, so for example (NULL is a where a default value for an attribute is not set):
Default
|0|NULL|
Variation 1:
|0|2| -> The 0 matches, but the 2 does not, so this is not default!
Variation 2:
|0|NULL| -> This is the default
To achieve this, I added the getAssignedAttributeCount()
function.
Also note that if no default variation is set, or no variation matching the default values is found, then the first variation is returned.
Upvotes: 0
Reputation: 254492
To get the default attributes for a variable product you can use WC_Product
method get_default_attributes()
this way:
<?php
global $product;
if( $product->is_type('variable') ){
$default_attributes = $product->get_default_attributes();
// Testing raw output
var_dump($default_attributes);
}
?>
Now to find out which is the corresponding product variation for this "defaults" attributes, is a little more complicated:
<?php
global $product;
if( $product->is_type('variable') ){
$default_attributes = $product->get_default_attributes();
foreach($product->get_available_variations() as $variation_values ){
foreach($variation_values['attributes'] as $key => $attribute_value ){
$attribute_name = str_replace( 'attribute_', '', $key );
$default_value = $product->get_variation_default_attribute($attribute_name);
if( $default_value == $attribute_value ){
$is_default_variation = true;
} else {
$is_default_variation = false;
break; // Stop this loop to start next main lopp
}
}
if( $is_default_variation ){
$variation_id = $variation_values['variation_id'];
break; // Stop the main loop
}
}
// Now we get the default variation data
if( $is_default_variation ){
// Raw output of available "default" variation details data
echo '<pre>'; print_r($variation_values); echo '</pre>';
// Get the "default" WC_Product_Variation object to use available methods
$default_variation = wc_get_product($variation_id);
// Get The active price
$price = $default_variation->get_price();
}
}
?>
This is tested and works.
Upvotes: 18