woocommerce_package_rates

Filters the calculation of shipping rates for a package. Calculates each shipping methods cost. Rates are stored in the session based on the package hash to avoid re-calculation every page load.

Available Parameters

array $package['rates'] - available rates
array $package - Package of cart items

Source code: woocommerce_package_rates

Code Example 1

Following code works in association with Woocommerce Pickup Locations plugin. If pickup location is activated and any of the products in cart is from a certain defined category (or categories), we will only show pickup location as the only shipping method, hiding all other shipping methods.

function careless_local_pickup_for_pickup_only_category( $rates, $package ) {
    //lets define our categories - we are using category slug
    $our_categories = array ( 'pickup-only', 'quick-pickup' );//MODIFY as needed

    $found = false;
    
    //check all cart items, if any of them are from our above defined categories or not 
    //finding only one will be enough
    foreach ( $package['contents'] as $item ) {
        if ( has_term( $our_categories, 'product_cat', $item['product_id'] ) ) {
            $found = true;
            break;
        }
    }
    
    $rates_arr = array();
    
    if ( !$found ) {
        return $rates;
    }
    
    foreach ( $rates as $rate_id => $rate ) {
        //pickup-location-method = name/id of the local pickup shipping method via "Woocommerce Pickup Location"s plugin 
        if ( 'pickup-location-method' === $rate->method_id ) {
            $rates_arr [ $rate_id ] = $rate;
        }
    }
    
    if ( !empty( $rates_arr ) ) {
        return $rates_arr;
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'careless_local_pickup_for_pickup_only_category', 100, 2 );

Code Example 2

Unset flat rate shipping if cart has any product from a specific shipping class and shipping zone is a specific shipping zone.

function careless_shipping_zone_and_class_delivery_options( $rates, $package ) {
    //lets define our shipping zone id
    $our_shipping_zone_id = 1;//MODIFY as needed
    //our shipping class id
    $our_shipping_class_id = 75;//MODIFY as needed

    //get shipping zone of the package
    $shipping_zone = wc_get_shipping_zone( $package );

    //get shipping zone id from shipping zone
    $zone_id = $shipping_zone->get_id();

    //let's see if package has our defined shipping zone
    if ( $zone_id !== $our_shipping_zone_id ) {
        return $rates;
    }

    //now we go through cart items and check for our shipping class
    foreach( WC()->cart->get_cart() as $cart_item  ) {
        $product = $cart_item[ 'data' ];//WC_Product object
        $shipping_class_id = $product->get_shipping_class_id();

        if( isset($rates['flat_rate:3']) && $shipping_class_id === $our_shipping_class_id ) {
            unset( $rates['flat_rate:3'] );//remove flat rate shipping
            break;
        }
    }

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

Code Example 3

Hide other shipping options/rates if free shipping is available.

function careless_hide_shipping_when_free_is_available( $rates ) {
    $rates_arr = array();
    foreach ( $rates as $rate_id => $rate ) {
        if ( 'free_shipping' === $rate->method_id ) {
            $rates_arr[ $rate_id ] = $rate;
            break;
        }
    }

    if ( !empty( $rates_arr ) ) {
        return $rates_arr;
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'careless_hide_shipping_when_free_is_available', 100 );

Code Example 4

Only show local pickup and free shipping, and hide other shipping options/rates, if both of them are available.

function careless_free_and_local_shipping( $rates ) {
    $rates_arr = array();
    
    foreach ( $rates as $rate_id => $rate ) {
        //only free_shipping and local_pickup
        if ( 'free_shipping' === $rate->method_id || 'local_pickup' === $rate->method_id ) {
            $rates_arr[ $rate_id ] = $rate;
        }
    }

    if ( ! empty( $rates_arr ) ) {
        return $rates_arr;

    }
    
    return $rates;
}

add_filter( 'woocommerce_package_rates', 'careless_free_and_local_shipping', 100 );

All example code goes in the functions.php file of your active theme.