Basically I'm trying to hide the flat rate shipping method "flat_rate:8" when in the cart there is only specific shipping classes (ID 40 to 46 included). However, when in the cart there is any products with shipping classes 47, 48, 49, I want to hide all other shipping methods except this "flat_rate:8". All the details below.
I have 9 shipping class (from ID 40 to 46): XXS, XS, S, ... L, XL, XXL, XXXL and and 5 shipping methods (flate_rate3, local_pickup, flat_rate6, flat_rate7, flat_rate8).
When in my cart I have:
- A mix a products and at least one of them is either XL, XXL or XXXL
- only XL, XXL or XXXL products (one or many)
I only want 2 shipping methods to be offered (local_pickup and flate_rate8). Basically, if any >= XL is in the cart, I only want these two methods to appear. I was able with this code to do these 3 pieces of code:
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your shipping class to find. 47 = shipping class XL
$class = 47;
// HERE define the shipping methods you want to hide
$method_key_ids = array('flat_rate:3', 'flat_rate:6', 'flat_rate:7');
// Checking in cart items
foreach( $package['contents'] as $item ) {
// If we find the shipping class
if( $item['data']->get_shipping_class_id() == $class ){
foreach( $method_key_ids as $method_key_id ){
unset($rates[$method_key_id]); // Remove the targeted methods
}
break; // Stop the loop
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your shipping class to find. 48 = shipping class XXL
$class = 48;
// HERE define the shipping methods you want to hide
$method_key_ids = array('flat_rate:3', 'flat_rate:6', 'flat_rate:7');
// Checking in cart items
foreach( $package['contents'] as $item ) {
// If we find the shipping class
if( $item['data']->get_shipping_class_id() == $class ){
foreach( $method_key_ids as $method_key_id ){
unset($rates[$method_key_id]); // Remove the targeted methods
}
break; // Stop the loop
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your shipping class to find. 49 = shipping class XXXL
$class = 49;
// HERE define the shipping methods you want to hide
$method_key_ids = array('flat_rate:3', 'flat_rate:6', 'flat_rate:7');
// Checking in cart items
foreach( $package['contents'] as $item ) {
// If we find the shipping class
if( $item['data']->get_shipping_class_id() == $class ){
foreach( $method_key_ids as $method_key_id ){
unset($rates[$method_key_id]); // Remove the targeted methods
}
break; // Stop the loop
}
}
return $rates;
}
This is doing the job, only 2 shipping methods are displayed now (local_pickup and flat_rate8).
Then, what I'm looking to do is:
When in my cart I have:
- only products with a shipping class of XXXS (id=40), XXS (41), XS (43), S (44), M (45), L (46)
I want to remove flat_rate8 and leave available all the other shipping methods. With the current code and setting, right now, when in my cart I have =< L products, I have all the methods available.
I've been trying to replicate the code shown above to hide this flat_rate8 only with "small" products are in the cart but obviously it won't work because when I have a mix cart (XXXL and S for example) it will remove flat_rate8 from the option.
I tried, in addition to the piece of code show above to add this:
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_classd', 10, 2 );
function hide_shipping_method_based_on_shipping_classd( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
return;
}
foreach( $package['contents'] as $package_item ){ // Look at the shipping class of each item in package
$product_id = $package_item['product_id']; // Grab product_id
$_product = wc_get_product( $product_id ); // Get product info using that id
if( $_product->get_shipping_class_id() != 47 ){ // If we DON'T find this shipping class ID (XL)
unset($rates['flat_rate:8']); // Then remove this shipping method
break; // Stop the loop, since we've already removed the shipping method from this package
}
}
return $rates;
}
But it doesnt work:
- When I have a XL product (id=47) and a S product in the cart, the flat_rate8 is not visibile (It should be, it's a mix of big and small products)
- When I have only XL product flat_rate8 is here (it's good)
- When I have small products (XS, S, M, etc.), flat_rate8 is not here (it's good)
I've been looking around many topics, among them:
- Hide shipping methods for specific shipping class in WooCommerce
- Conditionally Hide WooCommerce Shipping methods based on shipping class
But I can't figure out a solution to my issue.
Try the following code, where everything is merged in a unique hooked function:
Code goes in functions.php file of the active child theme (or active theme). It should works.