Skip to content
Advertisement

Add extra cost to flat rate shipping each 2 items from specific category in WooCommerce

Based on Add an additional cost to flat rate shipping each 3 items in Woocommerce answer code, I have made some changes to add an additional cost to flat are shipping method each 2 items (instead of each 3 items) and only when there are exclusively items from a specific category (here “T-Shirts” category).

Here’s my code attempt:

// add X amount to shipping for every 2 items added to the cart (flat rate only)
add_filter('woocommerce_package_rates', 'shipping_additional_cost_each_three_items', 100, 2);
function shipping_additional_cost_each_three_items( $rates, $package ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return $rates;

    // HERE set your additional shipping cost
    $additional_cost = 8.40;
    $items_count = WC()->cart->get_cart_contents_count();

    // Define/replace here your correct category slug (!)
    $product_category = 't-shirts';
    $prod_cat = false;

    // Going through each item in cart to see if there is anyone of your category        
    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;
        }
    }

    // Loop through the shipping taxes array
    foreach ( $rates as $rate_key => $rate ){
        $has_taxes = false;

        // Targetting "flat rate"
        if( 'flat_rate' === $rate->method_id ){

            // Get the initial cost
            $initial_cost = $new_cost = $rates[$rate_key]->cost;

            // Adding the additional cost if product in T-Shirt category after every 2 items (3, 6, 9 …)
            if ( $prod_cat ) {

                for($i = 0; $i <= $items_count; $i+=3){
                    $new_cost += $additional_cost;
                }
            }

            // Set the new cost
            $rates[$rate_key]->cost = $new_cost;

            // Taxes rate cost (if enabled)
            $taxes = [];

            // Loop through the shipping taxes array (as they can be many)
            foreach ($rates[$rate_key]->taxes as $key => $tax){
                if( $rates[$rate_key]->taxes[$key] > 0 ){
                    // Get the initial tax cost
                    $initial_tax_cost = $new_tax_cost = $rates[$rate_key]->taxes[$key];

                    // Get the tax rate conversion
                    $tax_rate    = $initial_tax_cost / $initial_cost;

                    // Set the new tax cost
                    $taxes[$key] = $new_cost * $tax_rate;
                    $has_taxes   = true; // Enabling tax
                }
            }
        } 
        if( $has_taxes )
            $rates[$rate_key]->taxes = $taxes;

        return $rates;
    }
}

For “Flat rate” chosen shipping method, the code works just fine when items from “t-shirts” category are in the cart. But if there is an item that doesn’t belongs to “t-shirt” category, the rate just disappears and shows the title with no amount.

Can someone tell me where I have to place the condition ‘if category is X’, to make that code functional?

Advertisement

Answer

There are some mistakes in your code (like return $rates; that should need to be just before last closing bracket). Try the following revisited code instead:

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

    // HERE set your additional shipping cost
    $additional_cost = 8.40;
    $each_items      = 2; // Number of items (for additional cost)

    // Her set your category(ies) (can be term Ids slugs or names)
    $product_categories = array('t-shirts');
    $items_cat_count    = 0; // Initializing

    // Loop through cart items for the current shipping package        
    foreach( $package['contents'] as $cart_item ) {
        if ( ! has_term( $product_categories, 'product_cat', $cart_item['product_id'] ) ){
            $items_cat_count += $cart_item['quantity']; // Count items from defined category
        }
    }
    
    if ( $items_cat_count >= $each_items ) {
       // Loop through the shipping taxes array
        foreach ( $rates as $rate_key => $rate ){
            // Targetting "flat rate"
            if( 'flat_rate' === $rate->method_id ){
                $initial_cost = $new_cost = $rate->cost; // Get the initial cost
                $has_taxes    = false; // Initializing
                $taxes        = array(); // Initializing
                
                // Adding to cost the additional cost each 2 items (2, 4, 6 …)
                for($i = 0; $i <= $items_cat_count; $i += $each_items){
                    $new_cost += $additional_cost;
                }
                $rates[$rate_key]->cost = $new_cost; // Set the new cost
                
                // Taxes rate cost (if any) - Loop through taxes array (as they can be many)
                foreach ($rate->taxes as $key => $tax){
                    if( $tax > 0 ){
                        // Get the initial tax cost
                        $initial_tax_cost = $new_tax_cost = $tax;
    
                        // Get the tax rate conversion
                        $tax_rate    = $initial_tax_cost / $initial_cost;
    
                        // Set the new tax cost in the array
                        $taxes[$key] = $new_cost * $tax_rate;
                        $has_taxes   = true; // Enabling tax changes
                    }
                }
                // set array of shipping tax cost
                if( $has_taxes ) {
                    $rates[$rate_key]->taxes = $taxes; 
                }
            } 
        }
    }
    return $rates;
}

Code goes in functions.php file of the active child theme (or active theme). It should works.

Don’t forget to empty your cart to refresh shipping cached data.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement