Jean R.
Jean R.

Reputation: 544

Change default variation value for the same product according to the category woocommerce

I'm working on a way to display default variations value for the SAME product according to the category he is. For example, I sell a card with option blue & red. When the user comes by the category ONE, I want the default value is blue. If he comes by the category TWO, the value will be red.

I found a hook woocommerce_product_default_attributes, but I don't know how to use it .

Note : It seems that woocommerce recognize only one category per product even if your product is in two category.


Example (edit):

I have a product P.
Product P is in two categories : Cat 1 & Cat 2.
Also, product P has two variables : Blue & Red

When the user comes by Cat 1, I want the default value is Blue. If he comes by Cat 2, the value will be Red.

The answer code of @LoicTheAztech (below) works, BUT:

When I go to Cat 1 or Cat 2, I can see that for Woocommerce, the product is only in Cat 1, even if we can access by both category.

So before everything, I need to solve the woocommerce issue.

Upvotes: 3

Views: 5384

Answers (2)

LoicTheAztec
LoicTheAztec

Reputation: 253901

New updated answer HERE with the replacement filter hook, as since WooCommerce 3, get_variation_default_attributes() method is replaced by get_default_attributes() and woocommerce_product_get_default_attributes is the new related filter hook to be used.


Before WooCommerce 3, the filter hook woocommerce_product_default_attributes was located in get_variation_default_attributes() deprecated method, so it's not really the right hook to achieve what you want.

You can achieve your conditional function in woocommerce_before_add_to_cart_form action hook, for example.

Notes:

  • Product Attribute taxonomy always begin by 'pa_' + the attribute slug
  • You need to set in for variable products the default value for this attribute in the variation tab settings.

The code:

add_action( 'woocommerce_before_add_to_cart_form', function(){
    global $product;

    // We EXIT if it's not a variable product
    if( ! $product->is_type('variable') ) return;

    ## DEFINE HERE the desired product attribute taxonomy
    $pa_attribute = 'pa_color';
    $default_attribute_for_variation = $product->get_variation_default_attribute( $pa_attribute );

    // We EXIT if Product Attribute Color is not set as variation usage
    if( empty( $default_attribute_for_variation ) ) return;

    // Get the array of default attributes
    $default_attributes = $product->get_default_attributes();

    // For product category 'ONE => Attribute "blue" slug value
    if( has_term( 'clothing', 'product_cat', $product->get_id() ) )
        $default_attributes[$pa_attribute] = 'blue';

    // For product category 'TWO' => Attribute "blue" slug value
    elseif( has_term( 'TWO', 'product_cat', $product->get_id() ) )
        $default_attributes[$pa_attribute] = 'red';

    else return; // If no product categories match we exit

    // If a product category match we set the default attribute
    $product->set_default_attributes( $default_attributes );
}, 80, 0 );

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This code is tested and works.

Upvotes: 2

LoicTheAztec
LoicTheAztec

Reputation: 253901

Since Woocommerce 3 you can use woocommerce_product_get_default_attributes filter hook… So your code for your 2 product categories will be something like this:

add_filter( 'woocommerce_product_get_default_attributes', 'filtering_product_get_default_attributes', 10, 2 );
function filtering_product_get_default_attributes( $default_attributes, $product ){
    // We EXIT if it's not a variable product
    if( ! $product->is_type('variable') ) return $default_attributes;

    ## --- YOUR SETTINGS (below) --- ##

    // The desired product attribute taxonomy (always start with "pa_")
    $taxonomy = 'pa_color';

    $category1 = 'one' // The 1st product category (can be an ID, a slug or a name)
    $value1 = 'blue' // The corresponding desired attribute slug value for $category1

    $category2 = 'two' // The 2nd product category (can be an ID, a slug or a name)
    $value2 = 'red' // The corresponding desired attribute slug value for $category2

    ## --- The code --- ##

    // Get the default attribute used for variations for the defined taxonomy
    $default_attribute = $product->get_variation_default_attribute( $taxonomy );

    // We EXIT if define Product Attribute is not set for variation usage
    if( empty( $default_attribute ) ) return $default_attributes;

    // For product category slug 'one' => attribute slug value "blue"
    if( has_term( 'one', 'product_cat', $product->get_id() ) )
        $default_attributes[$taxonomy] = 'blue';

    // For product category slug 'two' => attribute slug value "red"
    elseif( has_term( 'two', 'product_cat', $product->get_id() ) )
        $default_attributes[$taxonomy] = 'red';

    else return $default_attributes; // If no product categories match we exit

    return $default_attributes; // Always return the values in a filter hook
}

Code goes in function.php file of your active child theme (or active theme). Not tested yet, but it should work.

Explanations:

Since Woocommerce 3 and new introduced CRUDS setter methods, when a method is using get_prop() WC_Data method, a dynamic hook based on the object type and the method name can be used (essentially for frontend: "view" context)

See this line $value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this ); in

and this linereturn 'woocommerce_' . $this->object_type . '_get_'; in

So the filter hook is dynamically made this way (where $this->object_type is equal to 'product'):

'woocommerce_' . $this->object_type . '_get_' . 'default_attributes'

with 2 arguments:

  • $attributes (the property value that replace $value)
  • $product (the class instance object that replace $this)

See it on Woocommerce Github closed and solved issue

Upvotes: 2

Related Questions