-
-
Save kane-c/5e4d53601564ed667fb9 to your computer and use it in GitHub Desktop.
<?php | |
// Force pickup as a shipping option if one or more products in the catalog is marked as pickup only. | |
// To do this, add a shipping class with the slug 'pickup-only' then set products with that class as required. | |
// Add this script to your theme's functions.php or similar. | |
function hideShippingWhenPickupRequired($rates, $package) | |
{ | |
foreach ($package['contents'] as $item) { | |
$product = $item['data']; | |
$shippingClass = $product->get_shipping_class(); | |
if ('pickup-only' === $shippingClass) { | |
// The cart requires pickup | |
return array( | |
'local_pickup' => $rates['local_pickup'], | |
); | |
} | |
} | |
return $rates; | |
} | |
add_filter('woocommerce_package_rates', 'hideShippingWhenPickupRequired', 10, 2); |
Here is the updated function. Works in WooCommerce v3.4.4.
function hide_shipping_on_local_pickup_required( $rates, $package )
{
$local = [];
foreach( $package['contents'] as $item )
{
$product = $item['data'];
$shipping_class = $product->get_shipping_class();
if( $shipping_class == 'local-pickup' )
{
foreach( $rates as $rate_id => $rate )
{
if( 'local_pickup' === $rate->method_id )
{
$local[ $rate_id ] = $rate;
break;
}
}
}
}
return !empty( $local ) ? $local : $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_on_local_pickup_required', 10, 2 );
Works with WooCommerce v3.4.5 with a shipping plugin where local_pickup has been modified to legacy_local_pickup.
function hide_shipping_on_local_pickup_required( $rates, $package )
{
$local = [];
foreach( $package['contents'] as $item )
{
$product = $item['data'];
$shipping_class = $product->get_shipping_class();
if( $shipping_class == 'local-pickup' )
{
foreach( $rates as $rate_id => $rate )
{
if( in_array( $rate->method_id, array( 'local_pickup', 'legacy_local_pickup' ) ) )
{
$local[ $rate_id ] = $rate;
break;
}
}
}
}
return !empty( $local ) ? $local : $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_on_local_pickup_required', 10, 2 );
Hi there,
Couldn't make it work on Wordpress 4.9.9, Woocommerce 3.5.4 but here's what's been working out just fine for me :
function my_hide_shipping_when_local_is_available( $rates ) {
$local= array();
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$local[ $rate_id ] = $rate;
}
}
return !empty( $local ) ? $local : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_local_is_available', 100 );
Furthermore, I wanted to force the local pickup on my customer only when products with a specific shipping class were on the the cart.
Here's the final result :
// Replace 'shipping-class' with the specific shipping class you want to force the local pick up upon
// To make it more readable, replace $shippingClass with your class name, eg : $hugeProducts
function my_hide_shipping_when_local_is_available( $rates ) {
$cart_items = WC()->cart->get_cart();
$shippingClass = false;
foreach ( $cart_items as $cart_item ) {
$product = $cart_item['data'];
$class = $product->get_shipping_class();
if ( 'shipping-class' == $class ) {
$shippingClass = true;
}
}
$local = array();
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$local[ $rate_id ] = $rate;
}
}
if ( !empty($local) && ($shippingClass == true) ) {
return $local;
} else {
return $rates;
}
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_local_is_available', 100 );
Hi
Snippets above doesn't work for me, but I found this working solution: WooCommerce: Hide Shipping Rate if Shipping Class @ Cart
Clear transients after implementation!
/**
* @snippet Disable Free Shipping if Cart has Shipping Class (WooCommerce 2.6+)
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @testedwith WooCommerce 4.0
* @donate $9 https://businessbloomer.com/bloomer-armada/
*/
add_filter( 'woocommerce_package_rates', 'businessbloomer_hide_free_shipping_for_shipping_class', 10, 2 );
function businessbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$shipping_class_target = 59; // shipping class ID (to find it, see screenshot here: https://www.businessbloomer.com/woocommerce-disable-free-shipping-if-cart-has-shipping-class/ )
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset( $rates['flat_rate:1'] ); // shipping method with ID (to find it, see screenshot here: https://www.businessbloomer.com/woocommerce-disable-free-shipping-if-cart-has-shipping-class/)
}
return $rates;
}
I expanded the above snippets with an extra shipping class for products that are not delivered separately.
Tested with Wordpress 5.7.1 and WooCommerce 5.2.2
/**
* Hide all other methods if:
* - At least one item has shipping class 'local-pickup-only'
* OR
* - All items have shipping class 'no-individual-delivery'
**/
function check_local_pickup_only( $rates, $package ) {
$localPickupOnly = false;
$noIndividualDelivery = false;
$regularDelivery = false;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$class = $product->get_shipping_class();
switch ($class) {
case 'local-pickup-only':
$localPickupOnly = true;
break 2;
case 'no-individual-delivery':
$noIndividualDelivery = true;
break;
default:
$regularDelivery = true;
break;
}
}
if ( $noIndividualDelivery && !$regularDelivery ) {$localPickupOnly = true;}
$local = array();
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$local[ $rate_id ] = $rate;
}
}
if ( !empty($local) && ($localPickupOnly == true) ) {
return $local;
} else {
return $rates;
}
}
add_filter( 'woocommerce_package_rates', 'check_local_pickup_only', 10, 2 );
Here's my solution: for carts with one or more products belonging to the shipping class "Local Pickup Only" ($shipping_class_name = 'local-pickup-only'
), only the local pickup location(s) (from the Local Pickup in Blocks) will appear.
Tested with WordPress 6.5.2 and WooCommerce 8.7.0.
Important: "Clear customer sessions" after implementation (WooCommerce > Status > Tools > Clear customer sessions).
// WooCommerce display only "Local pickup" location(s) if one or more products added to the cart belong to the shipping class "Local Pickup Only". Dynamically unsets all shipping methods except those with values starting with "pickup_location:" if any product in the cart belongs to the "local-pickup-only" shipping class.
add_filter($hook_name='woocommerce_package_rates', $callback='woocommerce_shipping_method_local_pickup_only', $priority=10, $accepted_args=2);
function woocommerce_shipping_method_local_pickup_only( $rates, $package ) {
if ( WC() ) {
$shipping_class_name = 'local-pickup-only';
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values['data']->get_shipping_class() === $shipping_class_name ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
// Unset all shipping methods except for the ones with value starting with "pickup_location:"
foreach ( $rates as $rate_key => $rate ) {
if ( strpos( $rate_key, 'pickup_location:' ) !== 0 ) {
unset( $rates[ $rate_key ] );
}
}
}
return $rates;
}
}
Additionally, the snippet below removes the "Calculate shipping" for carts with one or more products belonging to the shipping class "Local Pickup Only" ($shipping_class_name = 'local-pickup-only'
).
// WooCommerce remove "Calculate shipping" if one or more products added to the cart belong to the shipping class "Local Pickup Only"
add_filter($hook_name='woocommerce_product_needs_shipping', $callback='woocommerce_shipping_method_local_pickup_only_remove_calculate_shipping', $priority=10, $accepted_args=1);
function woocommerce_shipping_method_local_pickup_only_remove_calculate_shipping() {
if ( WC() ) {
$shipping_class_name = 'local-pickup-only';
$in_cart = false;
$calculate_shipping = true;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values['data']->get_shipping_class() === $shipping_class_name ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
$calculate_shipping = false;
}
return $calculate_shipping;
}
}
This no longer works. It doesn't even allow me to pickup.