I offer free shipping for €45. I have hidden the other shipping methods, except local pick-up, when free is available using the code below.
add_filter( 'woocommerce_package_rates', 'hide_shipping_except_local_when_free_is_available', 100 );
function hide_shipping_except_local_when_free_is_available($rates) {
$free = $local = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
} elseif ( 'local_pickup' === $rate->method_id ) {
$local[ $rate_id ] = $rate;
}
}
return ! empty( $free ) ? array_merge( $free, $local ) : $rates;
}
My problem here is that Local pick-up must be free when cart subtotal is up to €45, so the customer must be able to choose between 2 free options (free shipping or local pick-up free) when free shipping is available or choose between paid shipping options.
I can't find the way to do it. Any help will be appreciated.
To offer also free local pickup when free shipping is available (keeping other shipping methods hidden), try to use the following code replacement (commented):
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 100, 2 );
function filter_woocommerce_package_rates( $rates, $package ) {
$free = array(); // Initializing variable
// 1st Loop (free shipping): Loop through shipping rates for the current shipping package
foreach ( $rates as $rate_key => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[$rate_key] = $rate;
break;
}
}
// 2nd Loop (local pickup): Loop through shipping rates for the current shipping package
foreach ( $rates as $rate_key => $rate ) {
// Set 'local_pickup' cost to zero when free shipping is available
if ( 'local_pickup' === $rate->method_id && ! empty($free) ) {
$taxes = array(); // Initializing variable
// Loop through tax costs
foreach ($rate->taxes as $key => $tax) {
$taxes[$key] = 0; // Set tax cost to zero
}
$rate->cost = 0; // Set cost to zero
$rate->taxes = $taxes; // Set back taxes costs array
$free[$rate_key] = $rate; // Set this rate into the $free array
break; // Remove this, if there is more than 1 Local pickup option for a shipping Zone
}
}
return ! empty($free) ? $free : $rates;
}
Code goes in functions.php file of your child theme (or in a plugin). It should work.
Important: You will have to empty your cart to refresh shipping method cache.
Other related threads: