I have several products in the store, however one product (flammable) can only be shipped via a specific shipping company; Unfortunately that company can’t reach the whole country. So in case the customer buys the flammable product and it’s outside the coverage of the only company that can ship the product, he should not see any other shipping option except local pickup.
So far I have this code (courtesy of different StackOverFlow answers):
function filter_woocommerce_package_rates( $rates, $package ) { // Shipping zone //echo 'entrando'; $shipping_zone = wc_get_shipping_zone( $package ); $product_ids = array( 2267 ); // HERE set the product IDs in the array $method_id = 'weight_based_shipping:38'; // HERE set the shipping method ID that I want to hide $found = false; // Get zone ID $zone_id = $shipping_zone->get_id(); //echo $shipping_zone; //echo $zone_id; // NOT equal if ( $zone_id != 8 ) { // Unset a single rate/method for a specific product foreach( $package['contents'] as $cart_item ) { if ( in_array( $cart_item['product_id'], $product_ids ) ){ $found = true; break; } } if ( $found ) unset( $rates[$method_id] ); } return $rates; } add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
however I don’t know why is not working. Even the ‘echo’ is not working.
Advertisement
Answer
Updated – Try following instead (code is commented):
// SETTINGS BELOW: Custom function that handle your settings function custom_shipping_settings() { return array( 'product_ids' => array(2267), // Define the products that need to be in a separated shipping package (local pickup) 'allowed_zones_ids' => array(8), // Define the allowed zones IDs ); } // Splitting cart items into 2 shipping packages add_filter( 'woocommerce_cart_shipping_packages', 'split_shipping_packages' ); function split_shipping_packages( $packages ) { extract(custom_shipping_settings()); // Load and extract settings $customer = WC()->customer; $destination = array( 'country' => $customer->get_shipping_country(), 'state' => $customer->get_shipping_state(), 'postcode' => $customer->get_shipping_postcode(), 'city' => $customer->get_shipping_city(), 'address' => $customer->get_shipping_address(), 'address_2' => $customer->get_shipping_address_2() ); $package_dest = array( 'destination' => $destination ); $zone = wc_get_shipping_zone( $package_dest ); if ( ! in_array( $zone->get_id(), $allowed_zones_ids ) ) { // Reset packages and initialize variables $packages = $splitted_cart_items = array(); // Loop through cart items foreach ( WC()->cart->get_cart() as $item_key => $item ) { if ( is_a($item['data'], 'WC_Product') && $item['data']->needs_shipping() ) { if ( ! array_intersect( array($item['product_id'], $item['variation_id']), $product_ids ) ) { $splitted_cart_items[0][$item_key] = $item; // Regular items } else { $splitted_cart_items[1][$item_key] = $item; // Special separated items } } } if ( count($splitted_cart_items) < 2 ) return $packages; // Loop through spitted cart items foreach ( $splitted_cart_items as $key => $items ) { // Set each cart items group in a shipping package $packages[$key] = array( 'contents' => $items, 'contents_cost' => array_sum( wp_list_pluck( $items, 'line_total' ) ), 'applied_coupons' => WC()->cart->get_applied_coupons(), 'user' => array( 'ID' => get_current_user_id() ), 'destination' => $destination, ); } } return $packages; } // Force local pickup for specific splitted shipping package (for the defined products) add_filter( 'woocommerce_package_rates', 'filter_wc_package_rates', 10, 2 ); function filter_wc_package_rates( $rates, $package ) { extract(custom_shipping_settings()); // Load and extract settings $zone = wc_get_shipping_zone( $package ); // Get current shipping zone $found = false; // For all others shipping zones than allowed zones if ( ! in_array( $zone->get_id(), $allowed_zones_ids ) ) { // Loop through cart items for current shipping package foreach( $package['contents'] as $item ) { // Look for defined specific product Ids if ( array_intersect( array($item['product_id'], $item['variation_id']), $product_ids ) ) { $found = true; // Flag as found break; // Stop the loop } } // If any defined product is in cart if ( $found ) { // Loop through shipping rates foreach ( $rates as $rate_key => $rate ) { // Hide all shipping methods keeping "Local pickup" if ( 'local_pickup' !== $rate->method_id ) { unset( $rates[$rate_key] ); } } } } return $rates; }
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Refresh the shipping caches:
- This code is already saved on your functions.php file.
- In a shipping zone settings, disable / save any shipping method, then enable back / save.
You are done and you can test it.