Search code examples
phpwordpresswoocommerceproductshipping-method

Set shipping cost conditionally based on a shipping class in Woocommerce


We're selling sample products on our Woocommerce site, which is just a variable product. The product has a unique shipping class that allows it to be delivered for 1.99.

Actually this cost is always set when if item belongs to that unique shipping class, even if there is other items.

I would like if possible to enable that shipping cost only if that specific item (from that unique shipping class) is alone in cart.

Any help is appreciated.


Solution

  • The following hooked function will set the shipping cost to 0 if an items with a specific shipping class are melted to other items:

    add_filter('woocommerce_package_rates', 'conditional_shipping_class_cost', 15, 2);
    function conditional_shipping_class_cost( $rates, $package ){
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return $rates;
    
        // HERE define the targeted shipping method
        $shipping_class = 'Extra';
    
        // Initializing variables
        $found = $others = false;
    
        // Loop through cart items and checking for the specific product
        foreach( $package['contents'] as $item ) {
            if( $item['data']->get_shipping_class() == sanitize_title($shipping_class) ){
                $found = true; // Has the shipping class
            } else {
                $others = true; // NOT the shipping class
            }
        }
    
        // When items with the defined shipping are not alone in cart
        if( $found && $others ){
            // Loop through shipping rates
            foreach ( $rates as $rate_key => $rate ){
                // For Flat rate and Local pickup shipping methods
                if( $rate->method_id == 'flat_rate' ) {
                    // Set the cost to zero
                    $rates[$rate_key]->cost = 0;
    
                    $rates[$rate_key]->label = 'f: '.$found.' | o: '.$others.' ';
    
                    // Initializing variables
                    $has_taxes = false;
                    $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 ){
                            // Set the tax cost to zero
                            $taxes[$key] = 0;
                            $has_taxes   = true;
                        }
                    }
                    // Set new taxes cost array
                    if( $has_taxes )
                        $rates[$rate_key]->taxes = $taxes;
                }
            }
        }
    
        return $rates;
    }
    

    This code goes on function.php file of your active child theme (or theme). Tested and works.