The question:
I currently have WooCommerce setup to allow free shipping on orders over a certain amount. However, I also have local pickup available and would like to allow BOTH if over a certain amount.
I have the following code to remove the other rates, however it also doesn’t keep the local pickup option.
function fd_shipping_rates( $rates, $package ) {
$all_free_rates = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$all_free_rates[ $rate_id ] = $rate;
break;
}
}
if ( empty( $all_free_rates )) {
return $rates;
} else {
return $all_free_rates;
}
}
add_filter( 'woocommerce_package_rates', 'fd_shipping_rates', 10, 2 );
Any help regarding this is much appreciated! I am looking for a code solution only as I am looking to minimise unneeded plugins.
EDIT: I recently found this article on WooCommerce Docs website regarding this exact issue.
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
The following code will disable other shipping methods excluding “Local Pickup” when “Free shipping” shipping method is available.
Required: Free shipping method need to be set with a minimal order amount.
add_filter( 'woocommerce_package_rates', 'show_hide_shipping_methods', 100 );
function show_hide_shipping_methods( $rates ) {
$free_rate_id = '';
$other_rates_ids = [];
// Loop through available shipping rates
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free_rate_id = $rate_id; // grab "Free shipping" rate ID
}
// Get all other rates Ids (excluding "Free shipping" and "Local pickup" methods)
if ( ! in_array( $rate->method_id, ['free_shipping', 'local_pickup'] ) ) {
$other_rates_ids[] = $rate_id;
}
}
// Disable All other rates Ids when "Free shipping" is available (excl. "Local pickup")
if ( ! empty($free_rate_id) && isset($rates[$free_rate_id]) && sizeof($other_rates_ids) > 0 ) {
foreach ( $other_rates_ids as $rate_id ) {
unset($rates[$rate_id]);
}
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.
Refresh the shipping caches: (required)
- This code is already saved on your active theme’s function.php file.
- The cart is empty
- In a shipping zone settings, disable / save any shipping method, then enable back / save.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0