admin管理员组

文章数量:1431028

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

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

Share Improve this question edited Apr 26, 2019 at 16:12 LOTUSMS asked Apr 24, 2019 at 14:56 LOTUSMSLOTUSMS 1256 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 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.

本文标签: phpChanging Woocommerce flat rate every nth number of items