We have a large variety of products in WooCommerce, some of which are not our own and supplied. I am trying to set up a functionality where free shipping is disabled if the products in the cart belongs to "Extra" shipping class exclusively.
If there are any other products with it that are not in the shipping class 'Extra', free shipping would still apply. So if 5 products are in cart all with shipping class 'Extra' and no other products, there is a $5 charge. If there is any other product that is not in that shipping class, free shipping applies again.
I've scoured the internet for solutions and this is what I got so far:
function hide_shipping_methods( $available_shipping_methods, $package ) {
$shipping_classes = array( 'Extra', 'some-shipping-class-2' );
$excluded_methods = array( 'free_shipping' );
$found = $others = false;
$shipping_class_exists = false;
foreach( $package['contents'] as $key => $value )
if ( in_array( $value['data']->get_shipping_class(), $shipping_classes ) ) {
$shipping_class_exists = true;
break;
}else {
$others = true; // NOT the shipping class
break;
}
if ( $shipping_class_exists && !others) {
$methods_to_exclude = array();
foreach( $available_shipping_methods as $method => $method_obj )
if ( in_array( $method_obj->method_id, $excluded_methods ) )
$methods_to_exclude[] = $method;
if ( $methods_to_exclude )
foreach ( $methods_to_exclude as $method )
unset( $available_shipping_methods[$method] );
}
return $available_shipping_methods;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_methods', 10, 2 );
However it doesn't seem to be working. I have products already in the shipping class Extra, however whenever I add them to cart there is still free shipping.
There are some mistakes and your code can be simplified. To disable free shipping for specific shipping classes exclusively, try the following revisited code:
add_filter( 'woocommerce_package_rates', 'hide_free_shipping_conditionally', 10, 2 );
function hide_free_shipping_conditionally( $rates, $package ) {
// Define the targeted shipping classes slugs (not names)
$targeted_classes = array( 'extra' );
$found = $others = false; // Initializing
// Loop through cart items for current shipping package
foreach( $package['contents'] as $item ) {
if ( in_array( $item['data']->get_shipping_class(), $targeted_classes ) ) {
$found = true;
} else {
$others = true;
}
}
// When there are only items from specific shipping classes exclusively
if ( $found && ! $others ) {
// Loop through shipping methods for current shipping package
foreach( $rates as $rate_key => $rate ) {
// Targetting Free shipping methods
if ( 'free_shipping' === $rate->method_id ) {
unset($rates[$rate_key]); // Remove free shipping option(s)
}
}
}
return $rates;
}
Code goes in functions.php file of the active child theme (or active theme). It should work.
Doin't forget to empty your cart to refresh shipping cached data.