I have set up multiple shipping zones, which have their own shipping methods: flat rate, local pickup (free) and free shipping with a minimum subtotal. Products belonging to "leeggoed" product category, should be excluded from the subtotal calculation used to determine free shipping eligibility.
Not sure if it is important, but I'm using this code to hide the "Flat rate" when "Free shipping" becomes available:
function hide_shipping_when_free_is_available( $rates, $package ) {
$new_rates = array();
foreach ( $rates as $rate_id => $rate ) {
// Only modify rates if free_shipping is present.
if ( 'free_shipping' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}
if ( ! empty( $new_rates ) ) {
//Save local pickup if it's present.
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}
return $new_rates;
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
The code I'm currently debugging fails to apply free shipping when the adjusted subtotal reaches the threshold.
add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) {
$excluded_category = 'leeggoed'; // Category slug to exclude
$adjusted_total = 0; // Initialize adjusted total
// Step 1: Calculate the cart total excluding "leeggoed" products
foreach (WC()->cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$product_id = $product->get_id();
// Only count products that are NOT in the "leeggoed" category
if (!has_term($excluded_category, 'product_cat', $product_id)) {
$adjusted_total += $cart_item['line_subtotal'];
}
}
// Step 2: Retrieve the free shipping threshold for this shipping method
if (isset($shipping_method->min_amount)) {
$free_shipping_min_amount = (float) $shipping_method->min_amount;
} else {
$free_shipping_min_amount = 0; // Default to 0 if no threshold is set
}
// Step 3: Free shipping is only available if the adjusted total meets the threshold
return ($adjusted_total >= $free_shipping_min_amount);
}, 10, 3);
I have set up multiple shipping zones, which have their own shipping methods: flat rate, local pickup (free) and free shipping with a minimum subtotal. Products belonging to "leeggoed" product category, should be excluded from the subtotal calculation used to determine free shipping eligibility.
Not sure if it is important, but I'm using this code to hide the "Flat rate" when "Free shipping" becomes available:
function hide_shipping_when_free_is_available( $rates, $package ) {
$new_rates = array();
foreach ( $rates as $rate_id => $rate ) {
// Only modify rates if free_shipping is present.
if ( 'free_shipping' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}
if ( ! empty( $new_rates ) ) {
//Save local pickup if it's present.
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}
return $new_rates;
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
The code I'm currently debugging fails to apply free shipping when the adjusted subtotal reaches the threshold.
add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) {
$excluded_category = 'leeggoed'; // Category slug to exclude
$adjusted_total = 0; // Initialize adjusted total
// Step 1: Calculate the cart total excluding "leeggoed" products
foreach (WC()->cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$product_id = $product->get_id();
// Only count products that are NOT in the "leeggoed" category
if (!has_term($excluded_category, 'product_cat', $product_id)) {
$adjusted_total += $cart_item['line_subtotal'];
}
}
// Step 2: Retrieve the free shipping threshold for this shipping method
if (isset($shipping_method->min_amount)) {
$free_shipping_min_amount = (float) $shipping_method->min_amount;
} else {
$free_shipping_min_amount = 0; // Default to 0 if no threshold is set
}
// Step 3: Free shipping is only available if the adjusted total meets the threshold
return ($adjusted_total >= $free_shipping_min_amount);
}, 10, 3);
Share
Improve this question
edited Mar 6 at 14:53
LoicTheAztec
255k24 gold badges399 silver badges446 bronze badges
asked Mar 6 at 13:04
kenken
235 bronze badges
1 Answer
Reset to default 1There are some mistakes in your last hooked function, try the following instead:
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'enable_free_shipping_for_specific_categories', 10, 3 );
function enable_free_shipping_for_specific_categories( $is_available, $package, $shipping_method ) {
if ( ! isset($shipping_method->min_amount) || ! $shipping_method->min_amount ) return $is_available;
$excl_cat = 'leeggoed';
$subtotal = 0; // Initializing variable
// Loop through cart items for the current shipping package
foreach ( $package['contents'] as $item ) {
if ( ! has_term($excl_cat, 'product_cat', $item['product_id']) ) {
$subtotal += $item['line_subtotal'];
}
}
return $subtotal >= $shipping_method->min_amount;
}
It should work.