Guy Iusim
Guy Iusim

Reputation: 23

Filter Shipping method based on shipping class in Woocommerce 3

I have been searching for code to filter out any shipping methods other than local pick up, on checkout, when a product that has a specific shipping class selected (Only pickup, ex.) is in the cart (among other products).

I only found code that was outdated and that doesn't work on WC3+.

Upvotes: 2

Views: 6117

Answers (2)

Chad Reitsma
Chad Reitsma

Reputation: 176

If you want to use the shipping classes slug instead, this is easier:

//Only show "Local Pickup" if cart contains specific products with the pickup only shipping class
//Remove any others

add_filter( 'woocommerce_package_rates', 'check_for_local_pickuponly', 100, 2 );
function check_for_local_pickuponly( $rates, $package ) {

  // Loop through cart items checking for the defined shipping method slug
  $found = false;
  foreach( $package['contents'] as $cart_item ) {
    
    if ($cart_item['data']->get_shipping_class() == "pick-up-only") {
        $found = true;
        break;
    }
    
  }

  //If found remove rates that aren't Local pickup
  if ($found === true) {
    foreach( $rates as $rate_key => $rate ) {
        if ($rate->method_id  !== 'local_pickup'){
            unset($rates[$rate_key]);
          }
      }
  }

  return $rates;
}

Added bonus: Display a notice on the Cart + Checkout pages:

add_action( 'woocommerce_before_cart', 'local_pickup_only_notice' );
add_action( 'woocommerce_before_checkout_form', 'local_pickup_only_notice' );
function local_pickup_only_notice() {

// Loop through cart items and check for the shipping classes slug
foreach ( WC()->cart->get_cart() as $item ) {
    
    if ($item['data']->get_shipping_class() == 'pick-up-only') {
    
        // Display a notice
        wc_print_notice( __("<strong>Shipping alert:</strong> Your cart contains items that cannot be shipped. Only local pickup is available."), 'notice' );
        break; 
        
    }
}}

Upvotes: 0

LoicTheAztec
LoicTheAztec

Reputation: 253814

Here is the way to filter out any shipping methods other than local pick up, when a product that has a specific shipping class enabled:

add_filter( 'woocommerce_package_rates', 'custom_shipping_rates', 100, 2 );
function custom_shipping_rates( $rates, $package ) {

    $shipping_class = 64; // HERE set the shipping class ID
    $found = false;

    // Loop through cart items Checking for the defined shipping method
    foreach( $package['contents'] as $cart_item ) {
        if ( $cart_item['data']->get_shipping_class_id() == $shipping_class ){
            $found = true;
            break;
        }
    }

    if ( ! $found ) return $rates; // If not found we exit

    // Loop through shipping methods
    foreach( $rates as $rate_key => $rate ) {
        // all other shipping methods other than "Local Pickup"
        if ( 'local_pickup' !== $rate->method_id && $found ){

            // Your code here
        }
    }

    return $rates;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works

Then in StackOverFlow searching for recent answer with woocommerce_package_rates will allow you to finish your code.

Upvotes: 2

Related Questions