Zahid Iqbal Zahid Iqbal - 3 months ago 18
PHP Question

Shipping methods - Local Pickup option not available when Flat Rate is hidden

Based on this answer (code below), I successfully can hide flat rate from particular product category and local delivery option is available. This is working perfect.

The problem: local pickup option is NOT available for that particular category.

How can I make the local pickup option available to this special category?

This is the code that I use:

function custom_shipping_methods( $rates ){

// Define/replace here your correct category slug (!)
$cat_slug = 'your_category_slug';
$prod_cat = false;

// Going through each item in cart to see if there is anyone of your category
foreach ( WC()->cart->get_cart() as $values ) {
$item = $values['data'];

if ( has_term( $cat_slug, 'product_cat', $item->id ) )
$prod_cat = true;
}

$rates_arr = array();

if ( $prod_cat ) {
foreach($rates as $key => $rate) {
if ('free_shipping' === $rate->method_id || 'local_pickup' === $rate->method_id || 'local_delivery' === $rate->method_id) {
$rates_arr[ $rate_id ] = $rate;
break;
}
}
}
return !empty( $rates_arr ) ? $rates_arr : $rates;
}
add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 100);


One more thing: Is it possible to show local delivery and local pickup for that special category depending on location?

Currently in my store local Pickup or Delivery is setup only for one location.

Answer

Advice: The code below is ONLY for WooCommerce version 2.6+…

Ok I got the answer, after many tests… You have to change 2 little things in your code:

function custom_shipping_methods( $rates ){

    // Define/replace here your correct category slug (!)
    $cat_slug = 'posters';
    $prod_cat = false;

    // Going through each item in cart to see if there is anyone of your category
    foreach ( WC()->cart->get_cart() as $values ) {
        $item = $values['data'];

        if ( has_term( $cat_slug, 'product_cat', $item->id ) )
            $prod_cat = true;
    }

    $rates_arr = array();

    if ( $prod_cat ) {
        foreach($rates as $rate_id => $rate) { // <== There was a mistake here

            if ('free_shipping' === $rate->method_id || 'local_pickup' === $rate->method_id || 'local_delivery' === $rate->method_id) {
                $rates_arr[ $rate_id ] = $rate;
                // break; // <========= Removed this to avoid stoping the loop
            }
        }
    }
    return !empty( $rates_arr ) ? $rates_arr : $rates;
}
add_filter( 'woocommerce_package_rates', 'custom_shipping_methods', 100);

Before adding the snippet, make sure you clear your WooCommerce cache (WooCommerce > System Status > Tools > WC Transients > Clear transients), as shipping methods are cached.

There was 2 mistakes:

  • One in the foreach loop with a bad variable name that I have replace it.
  • Removed break; avoiding stoping the foreach loop when one condition match.

This code goes on function.php file of your active child theme or theme.

This code is tested and fully functional (it will work if you have correctly set your shipping zones).


References: