skip to Main Content

I am encountering some issues with my condition to check for cart total, amongst cart quantity and shipping classes.

What I am trying to achieve

I am trying to hide a specific shipping method free_shipping:7 based on quantity of other specific shipping classes and cart total.

The problem I am encountering is that my conditional logic won’t work after using || (or) operator, it will not check for cart total, if I also check for quantity.

The code

/* Hide free shipping unless minimum of 6 bottle or 1 box is selected, or if 2 gins and under 600 cart total */

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

    // Shipping class to check for
    $class1 = 132; // shipping class for bottles
    $class2 = 131; // shipping class for boxes
    $class3 = 142; // shipping class for gin bottles

    // Shipping method to hide
    $ShipMethod_key_ids = array('free_shipping:7'); // free shipping

    // Get cart total of items in the cart, but after discounts. 
    $cart_totals =  WC()->cart->cart_contents_total;

    // Keep track of the quantity of items with the specified shipping class
    $quantity_bottle = 0;
    $quantity_gin = 0;
    $quantity_box = 0;

    // Loop through cart content and add to specified shipping classes
    if( $item['data']->get_shipping_class_id() == $class1 || $item['data']->get_shipping_class_id() == $class3){
        $quantity_bottle += $item['quantity'];
        $quantity_gin += $item['quantity'];
    }
    elseif (  $item['data']->get_shipping_class_id() == $class2 ) {
        $quantity_box += $item['quantity'];
    }
}

    // If there are less than 6 bottles, 6 gins, and less than 1 box
    // or 
    // if equal to 2 gins and less than 600 in Cart Total, hide the shipping method
    if( $quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1 || $quantity_gin == 2 && $cart_totals < 600 ) {
        foreach( $ShipMethod_key_ids as $method_key_id ){
            unset($rates[$method_key_id]);
        }
    }
    return $rates;
}

Problem

The problem I have is that the condition which checks for cart total, does not work when combined with || (or) operators.

if( $quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1 || $quantity_gin == 2 && $cart_totals < 600 ) {

If I use the combined example, as above, the code will neglect the last condition (2).

The condition will only work with one of the two:

  1. $quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1

  2. $quantity_gin == 2 && $cart_totals < 600

What I have tried

I have tried isolating the two conditions to check if they work. They do work on their own, but not in combination.

I have also tried to write them in separate if statements, but without any results.

Question

Can someone explain to me what am I doing wrong in this example? and what can I do to make it check for both statements?

Is it possible for me to achieve above without having to implement two different codes for each logic?

List of references

how to check the quantity of products in the woocommerce cart

Change flat rate shipping rate based on item cart totals belonging to specific shipping class

Conditionally Hide WooCommerce Shipping methods based on shipping class

Logical Operators – php manual

WC_Cart – WooCommerce Code Reference

2

Answers


  1. Chosen as BEST ANSWER

    So the major issue was with my logical expression. When we use || (OR), it will return true if either $a or $b is true. Whereas if we use && (AND) it will return true if both $a and $b are true.

    I also made sure to loop through cart items checking for shipping classes and add to the variables separately. This made my first expression invalid $quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1, but was needed for my second expression $quantity_gin == 2 && $cart_totals < 600. In order to make my first expression work, I add a new variable which counts bottle quantity and gin bottle quantity total.

    // Loop through cart content and add to specified shipping classes
    foreach( $package['contents'] as $item ) {
        if( $item['data']->get_shipping_class_id() == $class1 ){
            $quantity_bottle += $item['quantity'];
        }
        if( $item['data']->get_shipping_class_id() == $class3){
            $quantity_gin += $item['quantity'];
        }
        elseif (  $item['data']->get_shipping_class_id() == $class2 ) {
            $quantity_box += $item['quantity'];
        }
    }
    // Variable counting gin and other bottles
    $total_bottle_quantity_cart = $quantity_gin + $quantity_bottle;
    

    So the condition ended up being: if (($quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1 && $total_bottle_quantity_cart < 6 ) && !($quantity_gin >= 2 && $subtotaltax > 600 ) )

    The full code below:

    /* Hide free shipping unless minimum of 6 bottle or 1 box is selected, or if 2 gins and under 600 cart total */
    
    add_filter( 'woocommerce_package_rates', 'hide_free_shipping_method', 10, 2 );
    function hide_free_shipping_method( $rates, $package )
    {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
        // Shipping class to check for
        $class1 = 132; // shipping class for bottles
        $class2 = 131; // shipping class for boxes
        $class3 = 142; // shipping class for gin bottles
    
        // Shipping method to hide
        $ShipMethod_key_ids = array('free_shipping:7'); // free shipping
        // Get cart subtotal of items in the cart incl. tax, as a number
        $subtotal = WC()->cart->get_subtotal(); // Get cart subtotal value
        $subtax = WC()->cart->get_subtotal_tax(); // Get cart subtotal value tax
        $subtotaltax = $subtotal+$subtax; // calculate cart subtotal value with the tax added
      
        // Keep track of the quantity of items with the specified shipping class
        $quantity_bottle = 0;
        $quantity_gin = 0;
        $quantity_box = 0;
      
        // Loop through cart content and add to specified shipping classes
        foreach( $package['contents'] as $item ) {
            if( $item['data']->get_shipping_class_id() == $class1 ){
                $quantity_bottle += $item['quantity'];
            }
            if( $item['data']->get_shipping_class_id() == $class3){
                $quantity_gin += $item['quantity'];
            }
            elseif (  $item['data']->get_shipping_class_id() == $class2 ) {
                $quantity_box += $item['quantity'];
            }
        }
        // Variable counting gin and other bottles
        $total_bottle_quantity_cart = $quantity_gin + $quantity_bottle;
      
        // If there are less than 6 bottles, 6 gins, 1 box and less than 6 total bottles
        // or 
        // if gin quantity is not bigger than or equal to 2 and subtotal less than 600 
        // hide the shipping method
        if (($quantity_bottle < 6 && $quantity_gin < 6 && $quantity_box < 1 && $total_bottle_quantity_cart < 6 ) && !($quantity_gin >= 2  && $subtotaltax > 600 ) ) {
            foreach( $ShipMethod_key_ids as $method_key_id ){ 
                unset($rates[$method_key_id]);
            }
        }
        return $rates;
    }
    

  2. Could someone help me. I would like a code that gives me free shipping if I make a minimum purchase. The minimum value of 5 products is 1000

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