Add the min price difference in WooCommerce variable products attribute dropdown options

Viewed 114

I have products with multiple attributes allowing for multiple dimensions of variations. I'd like to show the price difference in the dropdown, but it is not comparing the absolute minimum price, for each option.

This is the code I am using:

add_filter( 'woocommerce_variation_option_name','display_price_in_variation_option_name');

function display_price_in_variation_option_name( $term ) {
    global $product;
    
if ( empty( $term ) ) {
    return $term;
}
if ( empty( $product->id ) ) {
    return $term;
}

$variation_id = $product->get_children();
$price_min = $product->get_variation_regular_price();

foreach ( $variation_id as $id ) {
    $_product       = new WC_Product_Variation( $id );
    $variation_data = $_product->get_variation_attributes();

    foreach ( $variation_data as $key => $data ) {

        if ( $data == $term ) {
            $html  = $term;
            $price_diff = $_product->get_price() - $price_min;
            $price_html = '';
            if ($price_diff > 0 ) { $price_html = ' (+£' . number_format((float)$price_diff, 2, '.', '') . ')';}
            $html  .= $price_html;
            return $html;
        }
    }
}
return $term;
}

However, this is only showing the minimum price of the current attribute, not the product as a whole.

the minimum price of the current attribute, not the product as a whole

I hope this is clear - ideally in the above image for options that do not add cost, $price_html should be blank. The code works perfectly for variations with a single attribute option, but does not work for variations with multiple attribute options.

1 Answers

Your code can be simplified and optimized, but it can't work with multiple attribute dropdowns. It can only work if there is a unique attribute dropdown (see the alternative way after).

So this code works only with one attribute dropdown:

add_filter( 'woocommerce_variation_option_name','display_diff_price_in_attribute_option_name', 10, 4 );
function display_diff_price_in_attribute_option_name( $term_name, $term, $attribute, $product ) {
    if ( ! is_a($product, 'WC_Product') || is_admin() ) {
        return $term_name;
    }
    $price_min = $product->get_variation_regular_price('min', true); // Min price for display

    foreach ( $product->get_children() as $variation_id ) {
        $variation  = wc_get_product($variation_id);
        $term_value = $variation->get_attribute($attribute);

        if ( $term_value == $term_name ) {
            $price_diff = wc_get_price_to_display($variation) - $price_min;

            if ($price_diff > 0 ) {
                $term_name .= ' (+' . strip_tags( wc_price( $price_diff ) ) . ')';
            }
            break;
        }
    }
    return $term_name;
}

So you need something different (when there is multiple attribute dropdowns).

The following code will display the price difference for the select variation, for example at the right of the selected variation price:

add_filter( 'woocommerce_available_variation', 'filter_available_variation_attributes', 10, 3 );
function filter_available_variation_attributes( $data, $product, $variation ){
    $price_min  = $product->get_variation_regular_price('min', true); // Min price for display
    $price_diff = $data['display_price'] - $price_min;

    if ($price_diff > 0 ) {
        $data['price_html'] = '<span class="price">' . $variation->get_price_html() . ' <em>(+' . wc_price( $price_diff ) . ')</em></span>';
    }
    return $data;
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

enter image description here

Related