I have two shipping methods in woocommerce, Flat Rate Standard (Method 1) and Flat Rate Express Post (Method 2). Two product categories, X and Z, can only use Method 1, so I want to hide Method 2 from the shipping choices at checkout if the cart contains any items from category X or Z.
I searched Stackoverflow and found this post Hide specific shipping method for specific products in Woocommerce and tried to apply the answer without success. The code I tried, with what I believe were the appropriate modifications, is below.
function specific_products_shipping_methods( $rates, $package ) {
$product_ids = array( 39 ); // HERE set the product IDs in the array
$method_id = 'Express_Post:5'; // HERE set the shipping method ID
$found = false;
// Loop through cart items Checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( in_array( $cart_item['product_id'], $product_ids ) ){
$found = true;
break;
}
}
if ( $found )
unset( $rates[$method_id] );
return $rates;
}
Shipping method 2 has an id:5 and the product category X has an id:39. I disabled,saved, enabled and saved shipping Method 2. When I add the above as a code snippet to the php file it either breaks the website (“Your site is experiencing technical difficulties”) or after entering the shipping address I will be stuck (spinning wheel) and so cannot get to the cart to check if the code is working.
[Update]
Thank you so much @Kelvin Mariano for your reply. I tried your code a number of times with several variations in case I had something wrong. I no longer get any errors, but both shipping methods still appear even if the cart contains an ineligible item.
The output of the echo for the relevant shipping method was this:
[flat_rate:5] => WC_Shipping_Rate Object
(
[data:protected] => Array
(`
[id] => flat_rate:5
[method_id] => flat_rate
[instance_id] => 5
[label] => Express Post
The code I tried was this:
function bz_specific_products_shipping_methods( $rates, $package ) {
$product_ids = array( 39 ); // HERE set the product IDs in the array
//$method_id = 'flat_rate:5'; // HERE set the shipping method ID
$method_id = 'flat_rate:5'; // HERE set the shipping method ID
$found = false;
/*
//please remove this comment to view all shipping methods and their information
`echo "<pre>";
print_r( $rates );
echo "</pre>";
exit();*/`
// Loop through cart items Checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( in_array( $cart_item['product_id'], $product_ids ) ){
$found = true;
break;
}
}
if ( $found ){
if( isset( $rates[$method_id] ) ){
unset( $rates[$method_id] );
}
}
return $rates;
}
//use the filter this is important
add_filter( 'woocommerce_package_rates','bz_specific_products_shipping_methods', 10, 2 );
Update 2
Array
(
[flat_rate:1] => WC_Shipping_Rate Object
(
[data:protected] => Array
(
[id] => flat_rate:1
[method_id] => flat_rate
[instance_id] => 1
[label] => Flat rate Standard
[cost] => 9.00
)
)
[flat_rate:5] => WC_Shipping_Rate Object
(
[data:protected] => Array
(
[id] => flat_rate:5
[method_id] => flat_rate
[instance_id] => 5
[label] => Express Post
[cost] => 11.77
2
Answers
I found the above code was interfering with the operation of the plugin WooCommerce Advanced Free Shipping. I de-activated that plugin and deleted the code above. I then installed Advanced Flat Rate Shipping for Woocommerce and that plugin allowed me to set parameters that prevented the two product categories from being eligible for shipping method 2.
I made two important changes, changed the name of the function to avoid conflicts, and changed the method I’m removing for a specific test.
Note that the methods from what I saw come with lowercase letters, make sure your method is really the first capital letters this will make a difference;
Note that I left a comment where you can use to see the ids correctly.
Note that I put an if before unset to avoid php errors
This worked perfectly in my tests here, you may not be giving the name correctly or your woocommerce or php are out of date so the site message is experiencing difficulties or the loop with the white screen