skip to Main Content

I’m trying to unset two shipping methods only if cart has 4 or less products from a specific shipping class.

Shipping Methods: flat_rate:20 and flat_rate:21

Shipping Class: 182

This is what I have:

add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Shipping Class To Find
    $class = 182;

    // Number Of Shipping Class Items In Cart
    $amount = 4;

    // Shipping Methods To Hide
    $method_key_ids = array('flat_rate:20', 'flat_rate:21');

    // Checking In Cart Items
    foreach( $package['contents'] as $item ) {
        // If We Find The Shipping Class and Number of Items
        if( $item['data']->get_shipping_class_id() == $class && count($package['contents']) <= $amount ){
            foreach( $method_key_ids as $method_key_id ){
                unset($rates[$method_key_id]); // Remove Targeted Methods
            }
            break; // Stop The Loop
        }
    }
    return $rates;
}

I would like to combine the above logic with the below logic:

add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package ) {
    $targeted_class_ids = array(182); // Shipping Class To Find
    $allowed_max_qty    = 4; // Max allowed quantity for the shipping class
    $shipping_rates_ids = array( // Shipping Method rates Ids To Hide
        'wf_shipping_ups:07',
        'wf_shipping_ups:08',
        'wf_shipping_ups:11',
        'wf_shipping_ups:54',
        'wf_shipping_ups:65',
        'wf_shipping_ups:70',
        'wf_shipping_ups:74',
        'free_shipping:2',
        'request_shipping_quote'
    );
    
    $related_total_qty  = 0;

    // Checking cart items for current package
    foreach( $package['contents'] as $key => $cart_item ) {
        if( in_array( $cart_item['data']->get_shipping_class_id(), $targeted_class_ids ) ){
            $related_total_qty += $cart_item['quantity'];
        }
    }
    
    // When total allowed quantity is more than allowed (for items from defined shipping classes)
    if ( $related_total_qty > $allowed_max_qty ) {
        // Hide related defined shipping methods
        foreach( $shipping_rates_ids as $shipping_rate_id ) {
            if( isset($rates[$shipping_rate_id]) ) {
                unset($rates[$shipping_rate_id]); // Remove Targeted Methods
            }
        }
    }
    return $rates;
}

To create the following logic:

1. If cart has 4 or less products in shipping class 181 unset the following shipping methods:

  • ‘flat_rate:20’
  • ‘flat_rate:21’

2. If cart has 5 or more products in shipping class 181 unset the following shipping method:

  • ‘wf_shipping_ups:07’
  • ‘wf_shipping_ups:08’
  • ‘wf_shipping_ups:11’
  • ‘wf_shipping_ups:54’
  • ‘wf_shipping_ups:65’
  • ‘wf_shipping_ups:70’
  • ‘wf_shipping_ups:74’
  • ‘free_shipping:2’
  • ‘request_shipping_quote’

Both codes work if I use them individually. But I get an error when I try to use both concurrently.

I get the following error: Cannot redeclare hide_shipping_method_based_on_shipping_class() (previously declared in /functions.php:272)

2

Answers


  1. I assume you’ve combined those two code snippet by writing them one after another.

    As you’ve used same function name twice, you got that error: Cannot redeclare…..

    So, you can try to fix it by renaming the function name of the 2nd snippet like this –

    add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class_logic_2', 10, 2 );
    function hide_shipping_method_based_on_shipping_class_logic_2( $rates, $package ) {
        // other stuffs
    }
    
    Login or Signup to reply.
  2. You should use different function names for each code snippet, but the best way is to merge everything in a unique function.

    Here is the way to make it work in a unique function (for items from specific shipping method(s)):

    • hiding some shipping methods when there are 4 or less items in cart
    • hiding some other shipping methods when there are 4 or less items in cart

    The code:

    add_filter( 'woocommerce_package_rates', 'show_hide_shipping_methods_based_on_shipping_class', 10, 2 );
    function show_hide_shipping_methods_based_on_shipping_class( $rates, $package ) {
        $targeted_class_ids  = array(182); // Shipping Class To Find
        
        $allowed_max_qty     = 4; // Max allowed quantity for the shipping class
        
        $shipping_rates_ids1 = array( // Shipping Method rates Ids To Hide if more than 4 items are in cart
            'wf_shipping_ups:07',
            'wf_shipping_ups:08',
            'wf_shipping_ups:11',
            'wf_shipping_ups:54',
            'wf_shipping_ups:65',
            'wf_shipping_ups:70',
            'wf_shipping_ups:74',
            'free_shipping:2',
            'request_shipping_quote',
        );
        
        $shipping_rates_ids2 = array( // Shipping Method rates Ids to Hide if 4 or less items are in cart
            'flat_rate:20',
            'flat_rate:20',
        );
        
        $related_total_qty   = 0; // Initializing
    
        // Checking cart items for current package
        foreach( $package['contents'] as $key => $cart_item ) {
            if( in_array( $cart_item['data']->get_shipping_class_id(), $targeted_class_ids ) ){
                $related_total_qty += $cart_item['quantity'];
            }
        }
        
        // When total allowed quantity is more than allowed (for items from defined shipping classes)
        if ( $related_total_qty > $allowed_max_qty ) {
            // Hide related defined shipping methods (more than 4 items)
            foreach( $shipping_rates_ids1 as $shipping_rate_id ) {
                if( isset($rates[$shipping_rate_id]) ) {
                    unset($rates[$shipping_rate_id]); // Remove Targeted Methods
                }
            }
        } else {
            // Hide related defined shipping methods (4 or less items)
            foreach( $shipping_rates_ids2 as $shipping_rate_id ) {
                if( isset($rates[$shipping_rate_id]) ) {
                    unset($rates[$shipping_rate_id]); // Remove Targeted Methods
                }
            }
        }
        return $rates;
    }
    

    Code goes in functions.php file of your active child theme (or active theme). Untested it should works.

    Refresh the shipping caches:

    1. This code is already saved on your functions.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.


    Handling number of items instead of items cumulated quantity:

    Replace:

    $related_total_qty += $cart_item['quantity'];
    

    by

    $related_total_qty++;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search