1

I found a semi-functional solution for my problem in this answer WooCommerce - Flat rate shipping based on X quantity steps? But this counts the total qty of the cart items which it doesn't quite work because if the customer adds a small item that can be packed together and this item bring the total of cart items over the threshold, it causes the shipping to double up. I need the shipping to double up ONLY when a specific class (i.e. Large Shipping class) exceeds the threshold. Here are some examples of what I need.

2 types of products in the site

  • Shirt (Can only send up to 3 in one package) - classed with "large shipping class"
  • Ring (Can send many of them in one package)

Because I can add the rings to the shirts package if a customer bought a combination of these two products, I have setup the shipping rates to charge the largest shipping class (large-shipping).

So here are some samples of orders

  • 3 Tshirts = $8 shipping
  • 3 Tshirts + 6 rings = $8 shipping
  • 4 Tshirts = $16 shipping (it doubles every 3s)
  • 4 Tshirts + 6 rings = $16 (it ignores the rings as cart qty)

This is what this code below is doing

  • 3 Tshirts = $8 shipping (Good)
  • 3 Tshirts + 1 ring = $16 shipping (not good)
  • 6 Tshirts = $16 shipping (good)

See my dilemma? Id like to modify this code below to count the items in a specific shipping class only, NOT the cart qty.

Here's the code

add_filter( 'woocommerce_package_rates', 
   'change_shipping_method_rate_based_on_shipping_class_2', 11, 2 );
   function change_shipping_method_rate_based_on_shipping_class_2( $rates, $package ){

        $items_count  = WC()->cart->get_cart_contents_count(); // Cart item count
        $items_change = 5; // number of items needed to increase the cost each time
        $rate_operand = ceil( $items_count / $items_change ); // Operand increase each 5 items here

        foreach ( $rates as $rate_key => $rate ){
           // Targetting "Flat rate"
           if( 'flat_rate' === $rate->method_id ) {
              $has_taxes = false;

              // Set the new cost
              $rates[$rate_key]->cost = $rate->cost * $rate_operand;

              // Taxes rate cost (if enabled)
              foreach ($rates[$rate_key]->taxes as $key => $tax){
                 if( $tax > 0 ){
                     // New tax calculated cost
                     $taxes[$key] = $tax * $rate_operand;
                     $has_taxes = true;
                 }
           }
           // Set new taxes cost
           if( $has_taxes )
           $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

Any help is appreciated

1 Answer 1

2

To change "Flat rate" shipping cost based on cart items quantity count that belongs to a specific shipping class, you will need something a bit different:

add_filter( 'woocommerce_package_rates', 'progressive_shipping_cost_based_shipping_class_quantity_steps', 10, 2 );
function progressive_shipping_cost_based_shipping_class_quantity_steps( $rates, $package )
{
    // HERE Bellow your settings
    $shipping_class = "large-shipping"; // The shipping class ID
    $qty_step       = 3; // Items qty threshold for a step
    $item_count     = 0; // Initializing

    // Get the shipping class ID
    $class_id = get_term_by('slug', $shipping_class, 'product_shipping_class' )->term_id;


    // Loop through in cart items to get the Tshirts count
    foreach( $package['contents'] as $cart_item ) {
        if ( $cart_item['data']->get_shipping_class_id() == $class_id ){
            $item_count += $cart_item['quantity']; // Count Tshirts
        }
    }

    // The rate operand increase each {$qty_step} depending on {$item_count}
    $rate_operand = ceil( $item_count / $qty_step );

    foreach ( $rates as $rate_key => $rate ){
        // Targetting "Flat rate"
        if( 'flat_rate' === $rate->method_id ) {
            $has_taxes = false;

            // Set the new cost
            $rates[$rate_key]->cost = $rate->cost * $rate_operand;

            // Taxes rate cost (if enabled)
            foreach ($rates[$rate_key]->taxes as $key => $tax){
                if( $tax > 0 ){
                    // New tax calculated cost
                    $taxes[$key] = $tax * $rate_operand;
                    $has_taxes = true;
                }
            }
            // Set new taxes cost
            if( $has_taxes )
                $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

Code goes in function.php file of your active child theme (or active theme). tested and works.

Refresh the shipping caches: (required)

  1. This code is already saved on your active theme's function.php file.
  2. The cart is empty
  3. In a shipping zone settings, disable / save any shipping method, then enable back / save.
2
  • Outstanding! I just realized you are the same one who answered the other question I referenced. I still owe you that beer haha
    – LOTUSMS
    Apr 25, 2019 at 12:33
  • 1
    @LOTUSMS hey thanks… could you please add the tag "php" to the question. Thanks. Apr 25, 2019 at 16:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.