Skip to content

Instantly share code, notes, and snippets.

@mikejolley
Forked from claudiosanches/functions.php
Last active February 5, 2024 15:33
Show Gist options
  • Save mikejolley/7ced4986b0b9c4b1fffedbe3e6bb6860 to your computer and use it in GitHub Desktop.
Save mikejolley/7ced4986b0b9c4b1fffedbe3e6bb6860 to your computer and use it in GitHub Desktop.
WooCommerce - Hide shipping rates when free shipping is available.
<?php
/**
* Hide shipping rates when free shipping is available.
* Updated to support WooCommerce 2.6 Shipping Zones.
*
* @param array $rates Array of rates found for the package.
* @return array
*/
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
@masjo
Copy link

masjo commented Dec 6, 2016

@EBonar try this

add_filter('woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2);
function hide_shipping_when_free_is_available($rates, $package) {
$free_yn = 0;
$pickup_yn = 0;
foreach($rates as $key => $value) {
$key_part = explode(":", $key);
$method_title = $key_part[0];
if ('free_shipping' == $method_title) {
// check if free shipping rate exists
$free_yn = 1;
$free_shipping = $rates[$key];
$free_key = $key;
}
if ('local_pickup' == $method_title) {
// check if local pickup rate exists
$pickup_yn = 1;
$local_pickup = $rates[$key];
$pickup_key = $key;
}
}
if ($free_yn == 1) {
// Unset all rates.
$rates = array();
// Restore free shipping rate.
$rates[$free_key] = $free_shipping;
if ($pickup_yn == 1) {
// Restore local pickup rate.
$rates[$pickup_key] = $local_pickup;
}
return $rates;
}
return $rates;
}

@mattiasghodsian
Copy link

@masjo this dose not work.

@haiflosse
Copy link

haiflosse commented May 14, 2017

I use two shipping Zone with different Minimum amount to get free shipping.
the Name of one shipping Zone is national and the other germany.
When a customer will order 49 euro in shipping Zone national it will be free shipping but when a customer in Germany must order 100 euro to get free shipping.
How can I solve this Problem.
kindly regards

I noticed that it will work automaticle. I forgot to add a free shipping in the Germany Zone.

@itsnidhu
Copy link

Hi I have a situation below:

  1. Customers get "Free Shipping" on orders above $100 but No 'Free Shipping' if 10% cart discount coupon code is used.
  2. "Flat Shipping" is $9.95 and "Express Shipping" is $13.95 but
    a) if Free Shipping applies Express Shipping should show $4.00 ($13.95 - $9.95)
    b) if coupon code of 10% cart discount is used no free shipping or no discount on Express shipping applies. i.e (Flat Shipping $9.95 and Express Shipping $13.95 applies if coupon code is used)

How can I do this.

I tried setting up the Shipping Zone
a) Free Shipping "A Minimum order amount or a coupon" - Minimum order $100
b) Flat Shipping - $9.95
c) Local Pickup - I customized this to "Express Shipping" with cost $13.95

Using the function

function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();

foreach ( $rates as $rate_id => $rate ) {

	if ( 'free_shipping' === $rate->method_id ) {
		$free[ $rate_id ] = $rate;
		 $free_shipping = true;
	}
	
	if ( $free_shipping == true && 'my_custom_shipping_method' === $rate->method_id ) {
        $free[ $rate_id ] = $rate;
    }
}
return ! empty( $free ) ? $free : $rates;

}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );

following things doesn't happen.

  1. If coupon code is not used
    a) For orders above $100 the express shipping is not showing along with 'Free Shipping'.
    Also the express shipping value should be (Flat Shipping $9.95 - Express Shipping $13.95) = $4

  2. If coupon code is used
    a) On using '10% cart discount - Coupon Code' on order $100 or more - Customers should only get 10% cart discount (coupon) and not get Free shipping or discount on express shipping. Therefore the shipping option should show Flat Shipping $9.95 and Express Shipping $13.95

    b) On using '10% cart discount - Coupon Code' on order under $100 - Customers should only get 10% cart discount (coupon). Therefore the shipping option should show Flat Shipping $9.95 and Express Shipping $13.95

How can I achieve this.

Please suggest.
Nidhi

@oblaum
Copy link

oblaum commented Oct 2, 2017

@masjo works very great!!!! thanks a thousand time. what i now need that the free shipping the first option is selected by default (at the moment none of the shipping mehthods are seleced.
screen checkout 1

@dambouvier
Copy link

dambouvier commented Feb 9, 2018

@masjo

Don't work for me :/
Is for 1 local pickup, but how to change this function for keep 2 local pickup ?

@desupero
Copy link

How would I hide other non-relevant shipping methods please? So if shipping for 1-3 items is $7 and 4-8 is $10, how would I hide the shipping option for $7, if the buyer has chosen 4-8 products please?

@ToddNewent
Copy link

ToddNewent commented Mar 14, 2018

Hey, so if you want to hide everything but free shipping and local pickup then modify @mikejolley code and change the foreach loop as follows:

foreach ( $rates as $rate_id => $rate ) {
  if ( 'free_shipping' === $rate->method_id ) {
    $free[ $rate_id ] = $rate;
  }

  if ( 'local_pickup' === $rate->method_id ) {
    $free[ $rate_id ] = $rate;
  }
}

@neoseeyou
Copy link

neoseeyou commented Mar 16, 2018

Hello

I want to display free shipping only when cart price is above 100 euros or if current user has a specific active membership and hide others shipping methods if possible

wc_memberships_is_user_active_member( $user_id, 'premium' )

If you could help me that would be really nice of you

Thanks

Cheers

@CarlosJGonzalez
Copy link

I added a field to categories to store a date. Using this same code, I exclude Flat_Rate option when the date in the custom field is greater than the current date.

@ngothoai
Copy link

i used this code

add_filter( 'woocommerce_package_rates', 'businessbloomer_hide_free_shipping_for_shipping_class', 10, 2 );

function businessbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$in_cart = false;
foreach( WC()->cart->cart_contents as $key => $values ) {
if( $values[ 'data' ]->get_shipping_class_id() ) {
$in_cart = true;
break;
}
}
if( $in_cart ) {
unset( $rates['ba_table_rate:7'] ); // shipping method with ID (to find it, see screenshot below)
}
return $rates;
}

But after i need remove Clear customer sessions after that, then it work.,

@Evakos
Copy link

Evakos commented Feb 14, 2019

May I ask why it's not considered a given that other shipping methods would be hidden if free is available? What would the case be where you would want other shipping methods to choose from? I can only think it may to do with expedited delivery options. Is that correct?

@kdctechnologies
Copy link

Hello can any one help me on the below issue
i have a single shipping zone with local pick up, free shipping 1500 above and flat rate if order valie less than 1500

i want to hide flat rate when order eligible for fee shipping and only free shipping and Local pick up should show

Thanks

@bullscout
Copy link

Hi i am having problem with this. where exactly i can put this code. I did insert on function.php but its not working and got error on my admin panel. All i want is the shipping works by their geographical location. Base on the customer location and under my shipping zone it will only shows the shipping options with free shipping or flat rate

@Abbas-5253
Copy link

Kindly help me out how can I change Zone regions postal code to cities ? I just want that when customer purchase from my website they can directly place city and get shipping charges, No Postal code, no region.

@eduande
Copy link

eduande commented Jul 13, 2020

@jamiet @pasztig: I've expanded on the provided function to hide all shipping options, except a custom shipping option I've added through a plugin.
function v161_woocommerce_hide_shipping_method( $rates ) {
$free = array();
$free_shipping = false;

    foreach ( $rates as $rate_id => $rate ) {

        if ( 'free_shipping' === $rate->method_id ) {

            $free[ $rate_id ] = $rate;
            $free_shipping = true;

        }

        if ( $free_shipping == true && 'my_custom_shipping_method' === $rate->method_id ) {
            $free[ $rate_id ] = $rate;
        }

    }

    return ! empty( $free ) ? $free : $rates;
}

Ofcourse you should be able replace the part
'my_custom_shipping_method' === $rate->method_id
with
'flat_rate:5' === $rate->id
or
'My custom shipping option name' === $rate->label

I've not tested the last 2 suggestions, but it should at least set you on the right track

Hello, good afternoon, I need to know how the exact code would be to incorporate, since I have two free shipping limits that I need at the time to display one or the other, depending on the minimum amount of purchase. Thank you so much

@Domi-ml
Copy link

Domi-ml commented Dec 3, 2020

Hello,

I would like to use the original code to display free shipping when I don't need to show flat rate anymore : it doesn't work.
I've tried on my local site to remove every other things from my functions.php : it still does not work.

What could be wrong ? I've tried to write my own filter before finding this one, and I couldn't understand what could be wrong.

Still my site is running normally offline and online, with all the other functions and plugins.

@jvorld
Copy link

jvorld commented Sep 17, 2021

The code for free shipping + local pickup didn't work for me, but I found a solution in the WooCommerce docs. Might be helpful for some.

https://docs.woocommerce.com/document/hide-other-shipping-methods-when-free-shipping-is-available/

@bdonkor
Copy link

bdonkor commented Nov 8, 2021

You have saved me out of a 1-week headache, I am grateful

@Mona88888
Copy link

Mona88888 commented Mar 14, 2022

What code to use if you want the shipping price to appear only for class specific and not based on amount spent?

@Mona88888
Copy link

I used the php coding and this is what happen to my Wordpress account = Parse error: syntax error, unexpected '*', expecting end of file in /home/customer/www/nrgispower.com/public_html/wp-content/themes/flatsome-child/functions.php on line 3

Fatal error: Exception thrown without a stack frame in Unknown on line 0

I am unable to login or see my account or website. HELP HELP HELP

@KoolPal
Copy link

KoolPal commented Jul 29, 2022

add_filter('woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2);
function hide_shipping_when_free_is_available($rates, $package) {
$free_yn = 0;
$pickup_yn = 0;
foreach($rates as $key => $value) {
$key_part = explode(":", $key);
$method_title = $key_part[0];
if ('free_shipping' == $method_title) {
// check if free shipping rate exists
$free_yn = 1;
$free_shipping = $rates[$key];
$free_key = $key;
}
if ('local_pickup' == $method_title) {
// check if local pickup rate exists
$pickup_yn = 1;
$local_pickup = $rates[$key];
$pickup_key = $key;
}
}
if ($free_yn == 1) {
// Unset all rates.
$rates = array();
// Restore free shipping rate.
$rates[$free_key] = $free_shipping;
if ($pickup_yn == 1) {
// Restore local pickup rate.
$rates[$pickup_key] = $local_pickup;
}
return $rates;
}
return $rates;
}

@masjo Brilliant! Still works awesome in 2022! God bless you!

@pmlgil
Copy link

pmlgil commented May 18, 2023

Hello

I have an online store where anyone who makes purchases over €30 can benefit from the “Free Shipping” or “Local Pickup” service at one of the two existing stores.

I integrated the PHP code to hide the shipping fees when the “Free Shipping” service is available (for purchases over €30) and also the “Local Pickup” option is visible… Everything worked perfectly.

The PHP code that I integrated, was this:

/**

  • Hide shipping rates when free shipping is available, but keep "Local pickup"
  • Updated to support WooCommerce 2.6 Shipping Zones
    */

function hide_shipping_when_free_is_available( $rates, $package ) {
$new_rates = array();
foreach ( $rates as $rate_id => $rate ) {
// Only modify rates if free_shipping is present.
if ( 'free_shipping' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}

if ( ! empty( $new_rates ) ) {
	//Save local pickup if it's present.
	foreach ( $rates as $rate_id => $rate ) {
		if ('local_pickup' === $rate->method_id ) {
			$new_rates[ $rate_id ] = $rate;
			break;
		}
	}
	return $new_rates;
}

return $rates;

}

add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );

However, the “Free Shipping” option is visible, but only one of the two pick-up locations.

Apart from making the “Free Shipping” option visible, is there any possibility to make all pick-up locations visible and not just one? There are currently two physical stores where “Local Pickup” is possible

Thanks.

@ilohest
Copy link

ilohest commented Jan 30, 2024

@Sjouw Tank you very much! It really helped me as I had to show "Local Pickup" with free shipping. I used the 'My custom shipping option name' === $rate->label' and it worked perfectly. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment