Disable only specific flat rate shipping method when free shipping is available in WooCommerce

I have two flat rates on my WooCommerce site and I want to disable one of them, when free shipping is enabled. I have a function which is working for all flat rates only.

How do I check for an instance id on a shipping rate? Can anyone help me understand how to check for the instance id?

I Was trying to echo shipping data out to make sense of what values were available but no echo was showing on the front end either so a tip on why would be great.

Here is my code attempt:

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;
            }
            if ( 'flat_rate:20' === $rate->instance_id )
                $new_rates[ $rate_id ] = $rate; 
            }
        return $new_rates;
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );

Answer

If you inspect the shipping methods radio buttons on cart or in checkout you will see something like:

<input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_flat_rate20" value="flat_rate:20" class="shipping_method" checked="checked">

So in value="flat_rate:20" (which is the rate Id):

  • the method Id is flat_rate,
  • and instance ID is 20.

Then you can change your code this way:

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 ) ) {
        foreach ( $rates as $rate_id => $rate ) {
            //Save local pickup if it's present.
            if ('local_pickup' === $rate->method_id ) {
                $new_rates[ $rate_id ] = $rate;
            }
            if ( 20 == $rate->instance_id )
                $new_rates[ $rate_id ] = $rate;
            }
        }
        return $new_rates;
    }
    return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );

It should work.

Leave a Reply

Your email address will not be published. Required fields are marked *