Search code examples
phpwordpresswoocommerceisset

Shipping options depending on cart weight and shipping class


I am working on a WordPress site that uses WooCommerce. I found this piece of code that allows me to set a freight shipping option based on weight. It worked great until the client also wanted the same freight shipping option if a freight shipping class is selected on a product.

add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );

function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {

  if ( WC()->cart->cart_contents_weight < 300 ) {

    if ( isset( $rates['fedex:PRIORITY_OVERNIGHT'], $rates['fedex:FEDEX_2_DAY'], $rates['fedex:FEDEX_GROUND'] ) );

  } else {

    if ( isset( $rates['flat_rate:10'] ) ) unset( $rates['fedex:PRIORITY_OVERNIGHT'], $rates['fedex:FEDEX_2_DAY'],$rates['fedex:FEDEX_GROUND'] );
  }

return $rates;
}

Then I found another piece of code that could set a shipping class to a shipping option. The code I found was mean to unset shipping options that are available but I want to isset the freight shipping since we unset it via the cart weight. However, I am running into an issue where the freight shipping class can no longer be set to isset without causing major issues. Below is what I tried to do for the freight shipping.

add_filter( 'woocommerce_package_rates', 'freight_shipping_class_only', 10, 2 );

function freight_shipping_class_only( $rates, $package ) {

  $shipping_class_target = 193;
  $in_cart = false;
  foreach( WC()->cart->cart_contents as $key => $values ) {
    if( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
      $in_cart = true;
      break;
    } 
  }
  if( $in_cart ) {
    unset( $rates['fedex:PRIORITY_OVERNIGHT'], $rates['fedex:FEDEX_2_DAY'],$rates['fedex:FEDEX_GROUND']  ); // shipping method with ID (to find it, see screenshot below)
    isset( $rates['flat_rate:10'] );
  }
  return $rates;
} 

Is there a way to set both the cart weight and the freight shipping class in one function? It would be ideal since I want them both to do the exact same thing by unset all FedEx shipping option and isset the freight shipping option.

Let me know if you need me to be clearer or if you have any tips.

Thanks!


Solution

  • As you are using 2 times the same hook, you can simply merge your functions in one.

    Now with php [isset()][1] you need to use it in as a condition in an IF statement to check if a variable is set (exist), but it has no effect alone outside your IF statement in your function.

    So in your first function the following doesn't has any effect:

    if ( isset( $rates['fedex:PRIORITY_OVERNIGHT'], $rates['fedex:FEDEX_2_DAY'], $rates['fedex:FEDEX_GROUND'] ) );
    

    So you can try this compact and efficient code instead:

    add_filter( 'woocommerce_package_rates', 'freight_shipping_class_only', 20, 2 );
    function freight_shipping_class_only( $rates, $package ) {
        // HERE the targeted shipping class ID
        $targeted_shipping_class = 193;
    
        // Loop through cart items and checking
        $found = false;
        foreach( $package['contents'] as $item ) {
            if( $item['data']->get_shipping_class_id() == $targeted_shipping_class ){
                $found = true;
                break;
            }
        } 
        
        // The condition
        if ( isset( $rates['flat_rate:10'] ) && ( WC()->cart->get_cart_contents_weight() >= 300 || $found ) ){
            unset( $rates['fedex:PRIORITY_OVERNIGHT'], $rates['fedex:FEDEX_2_DAY'], $rates['fedex:FEDEX_GROUND'] );
        }
    
        return $rates;
    }
    

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