Search code examples
phpwoocommerceshipping-method

WooCommerce - hide / show shipping methods based on cart subtotal


In my WooCommerce store (using version 4.2.2), I would like to hide / show some shipping methods based on cart subtotal as follow:

  • For less than 25 euros: show only shipping methods A and B,
  • Between 25 and 49 euros: show only shipping methods C and D,
  • For 50 euros or more: show only free shipping

Note shipping methods A, B, C and D are all "flat rate".

I have googled this and managed to get this trying the following code (I was just testing with one rate and one threshold):

add_filter( 'woocommerce_package_rates', 'hide_shipping', 10, 2 );
function hide_shipping( $rates, $package ) {
    // Retrieve cart subtotal
    global $woocommerce;
    $cart_subtotal = $woocommerce->cart->get_subtotal();
 
    if( $cart_subtotal > 25 ){
        unset( $rates['flat_rate:7'] );
    }
 
    return $rates;
}

But the code has no effect. Where am I going wrong?


Solution

  • Try the following (setting your 5 shipping methods rate Ids inside the code at the beginning). Also for your "free shipping" rate, set the "Minimum order amount" to 0 (zero).

    add_filter( 'woocommerce_package_rates', 'hide_specific_shipping_method', 10, 2 );
    function hide_specific_shipping_method( $rates, $package ) {
        // Settings: define you shipping rate IDs below
        $rate_id_1     = 'flat_rate:7';
        $rate_id_2     = 'flat_rate:11';
        $rate_id_3     = 'flat_rate:12';
        $rate_id_4     = 'flat_rate:15';
        $rate_free     = 'free_shipping:5';
        
        $cart_subtotal = WC()->cart->get_subtotal();
        
        if ( $cart_subtotal < 25 ) {
            // Enable only methods 1 et 2
            if ( isset($rates[$rate_id_3]) )
                 unset( $rates[$rate_id_3] );
            if ( isset($rates[$rate_id_4]) )
                 unset( $rates[$rate_id_4] );
            if ( isset($rates[$rate_free]) )
                 unset( $rates[$rate_free] );
        } 
        elseif ( $cart_subtotal >= 25 && $cart_subtotal < 50 ) {
            // Enable only methods 3 et 4
            if ( isset($rates[$rate_id_1]) )
                 unset( $rates[$rate_id_1] );
            if ( isset($rates[$rate_id_2]) )
                 unset( $rates[$rate_id_2] );
            if ( isset($rates[$rate_free]) )
                 unset( $rates[$rate_free] );
        } 
        else {
            // Enable only Free shipping
            if ( isset($rates[$rate_id_1]) )
                 unset( $rates[$rate_id_1] );
            if ( isset($rates[$rate_id_2]) )
                 unset( $rates[$rate_id_2] );
            if ( isset($rates[$rate_id_3]) )
                 unset( $rates[$rate_id_3] );
            if ( isset($rates[$rate_id_4]) )
                 unset( $rates[$rate_id_4] );
        }
        return $rates;
    }
    

    Code goes in functions.php file of your active child theme (or active theme). Tested and works.

    IMPORTANT: Refresh the shipping caches:
    1). This code is already saved on your function.php file.
    2). In a shipping zone settings, disable / save any shipping method, then enable back / save.
    You are done and you can test it.