Hide Flat Rate shipping exclusively for a product

2019-08-26 13:40发布

问题:

This is an extension of this question: Remove shipping Flat Rate method for particular Category in WooCommerce 2.6 and 3+

Used the Woo Smart Coupons plugin for a Gift Card product. This HAS to be set to Variation, as we have multiple tiers to select from. (this rules out virtual products) The Gift Card has it's own category for distinction. We have two shipping options set up: Flat Rate + Local Pickup. It's pretty silly to have shipping options for a gift card that gets sent to your Inbox, so I used the following snippet found in the link above:

add_filter( 'woocommerce_package_rates', 'conditional_hide_shipping_methods', 100, 2 );    
function conditional_hide_shipping_methods( $rates, $package ){

// Define/replace here your correct category slug (!)
$product_category = 'coupons-gift-cards';
$prod_cat = false;

foreach ( WC()->cart->get_cart() as $cart_item ) {
    $product_id = $cart_item['product_id'];
    if ( has_term( $product_category, 'product_cat', $product_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;
}

Works like a charm... until you add a product that ISN'T from that category. If someone decides that they want a Gift Card AND a normal product, then the regular shipping options need to be back in place.

EDIT: The checked answer works perfectly! If you want to change the Pickup Label for items like the above situation so they say something like "Download" instead of "Pickup", then add this line after the IF statement that checks which products are matching the categories

foreach( $rates as $rate_key => $rate ) {
//change local_pickup:1 to your shipping method
    if ( 'local_pickup:1' == $rate_key){
//set the text for the label
        $rates[$rate_key]->label = __( 'Download', 'woocommerce' );
    }
}

回答1:

Here is the correct way to make it work for a unique and exclusive product category, that will hide Flat rate exclusively if there is no others products remaining to this product category:

add_filter( 'woocommerce_package_rates', 'hide_shipping_flat_rate_conditionaly', 90, 2 );
function hide_shipping_flat_rate_conditionaly( $rates, $package ){

    // HERE Define your product category (ID, slug or name or an array of values)
    $term   = 'coupons-gift-cards';
    $others = $found = false;

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product_id = $cart_item['product_id'];
        if ( has_term( $term, 'product_cat', $cart_item['product_id'] ) )
            $found = true;
        else
            $others = true;
    }

    if ( $found && ! $others ) {
        foreach($rates as $rate_id => $rate) {
            if ('flat_rate' === $rate->method_id )
                unset($rates[ $rate_id ]);
        }
    }
    return $rates;
}

Code goes on function.php file of your active child theme (or active theme).

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

You might need to refresh shipping cached data: disable, save and enable, save related shipping methods for the current shipping zone, in Woocommerce shipping settings.