Search code examples
phpwordpresswoocommercehook-woocommerceproduct-variations

Filter hook woocommerce_product_get_weight doesn't work with product variations


It appears the woocommerce_product_get_weight hook that I have been using to override product weight (for the purpose of affecting the shipping calculation) is not firing for any of my product variations. It does fire for simple products though.

In the code below, you will see that I am writing to a log as soon as the function is called. Nothing is written when a product is a product variation. The only output is when the product is a simple product.

I am also beginning to wonder if this is the wrong way to override weight for this purpose. Any ideas?

My code is here:

function custom_weight($weight, $product)
{
    logvar($weight, "weight before");
    logvar($product, "variant terms - weight");
    if (!is_admin()) {

        $product_id = $product->get_id();
        if (has_term('weight-sheer', 'product_tag', $product_id))
            $weight = 1.5/16;
        elseif (has_term('weight-light', 'product_tag', $product_id))
            $weight = 7.5/16;
        elseif (has_term('weight-medium', 'product_tag', $product_id))
            $weight = 12/16;
        elseif (has_term('weight-heavy', 'product_tag', $product_id))
            $weight = 30/16;
        elseif (has_term('Thread', 'product_cat', $product_id))
            $weight = 0;
        elseif (has_term('Gift Cards', 'product_cat', $product_id))
            $weight = 0;
    }
    logvar($weight, "weight after");

    return $weight;
}

add_filter('woocommerce_product_get_weight', 'custom_weight', 25, 2);

//helper function for easy logging
function logvar($var, $label = null)
{
    if ($label != null) {
        wc_get_logger()->debug($label, array('source' => 'mylog'));
    }
    wc_get_logger()->debug(var_export($var, true), array('source' => 'mylog'));
}

Solution

  • First woocommerce_product_get_weight is a composite filter hook for WC_Product get_weight() method, but for product variations, you have to use woocommerce_product_variation_get_weight filter hook additionally.

    Also, as product variation doesn't handle WooCommerce product categories or tags, so you need to get the parent variable product ID to make it work with WordPress has_term() function like:

    add_filter( 'woocommerce_product_get_weight', 'filter_product_weight', 10, 2 );
    add_filter( 'woocommerce_product_variation_get_weight', 'filter_product_weight', 10, 2 );
    function filter_product_weight( $weight, $product ) {
        if ( is_admin() ) {
           return $weight;
        }
        $product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
            
        if ( has_term('weight-sheer', 'product_tag', $product_id) ) {
            $weight = 1.5/16;
        } elseif ( has_term('weight-light', 'product_tag', $product_id) ) {
            $weight = 7.5/16;
        } elseif ( has_term('weight-medium', 'product_tag', $product_id) ) {
            $weight = 12/16;
        } elseif ( has_term('weight-heavy', 'product_tag', $product_id) ) {
            $weight = 30/16;
        } 
    
        if ( has_term(array('Thread', 'Gift Cards'), 'product_cat', $product_id) ) {
            $weight = 0;
        } 
        return $weight;
    }
    

    Now it will work with all product types, including product variations.