Show only free shipping when over x amount issue in Woocommerce - php

I am trying to hide "flat-rate" if free shipping is available.
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_when_free_is_available', 100, 2 );
function hide_other_shipping_when_free_is_available( $rates, $package ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
I found the following snippet and added to my functions.php, but it does not hide the flat rate shipping option.

This code still perfectly works for woocommerce versions 2.6+ (so also 3.2.x)
The missing part is once you have saved your code in your function.php file, you need to refresh the shipping cached data:
Disable, save and enable, save related shipping methods for the current shipping zone, in woocommerce shipping settings.

Related

Shipping rate applied only if a certain coupon is used in WooCommerce

I need to create 2000 coupons to sell, but I would like the customers who will use them to always pay for shipping. Currently the threshold for getting free shipping is set above 69€. I tried to use the code below (taken from here: Applied coupons disable Free shipping conditionally in Woocommerce).
It applies to all coupons though, and I'd like to apply it only on coupons with the prefix 'pd'.
add_filter( 'woocommerce_package_rates', 'coupons_removes_free_shipping', 10, 2 );
function coupons_removes_free_shipping( $rates, $package ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
$applied_coupons = WC()->cart->get_applied_coupons();
if( sizeof($applied_coupons) > 0 ) {
// Loop through shipping rates
foreach ( $rates as $rate_key => $rate ) {
// Targeting "Free shipping" only
if( 'free_shipping' === $rate->method_id ) {
unset($rates[$rate_key]); // Removing current method
}
}
}
return $rates;
}

Keep highest flat rate shipping cost and local pickup in Woocommerce

I'm trying to show the highest shipping costs in the cart. I've found a nice little snippet for that:
function only_show_most_expensive_shipping_rate( $rates, $package ) {
$most_expensive_method = '';
$new_rates = array();
// Loop through shipping rates
if ( is_array( $rates ) ) {
foreach ( $rates as $key => $rate ) {
// Set variables when the rate is more expensive than the one saved
if ( empty( $most_expensive_method ) || $rate->cost > $most_expensive_method->cost ){
$most_expensive_method = $rate;
}
}
}
// Return the most expensive rate when possible
if ( ! empty( $most_expensive_method ) ){
/**
** Keep local pickup if it's present.
**/
foreach ( $rates as $rate_id => $rate ) {
if ('local_pickup' === $rate->method_id ) {
$new_rates[ $rate_id ] = $rate;
break;
}
}
return array( $most_expensive_method->id => $most_expensive_method );
}
return $rates;
}
add_action('woocommerce_package_rates', 'only_show_most_expensive_shipping_rate', 10, 2);
However this snippet also hides the "local pickup" shipping method.
Why does the above method doesn't work? Right now it only shows the highest shipping class/price and hide all others including the pickup method.
Is it because of the two arrays? I don't see any errors popping up.
Any help greatly appreciated!
The following will keep the highest shipping Flat rate cost and the Local pickup shipping method:
add_action('woocommerce_package_rates', 'keep_highest_flat_rate_cost', 10, 2);
function keep_highest_flat_rate_cost( $rates, $package ) {
$flat_rate_costs = [];
// Loop through shipping methods rates
foreach ( $rates as $key_rate => $rate ) {
// Targeting only "Flat rate" type shipping methods
if ( ! in_array( $rate->method_id, ['local_pickup', 'free_shipping'] ) ) {
// Store the Rate ID keys with corresponding costs in an indexed array
$flat_rate_costs[$key_rate] = $rate->cost;
}
}
// Sorting "Flat rate" costs in DESC order
arsort($flat_rate_costs);
// Remove the highest cost from the array
array_shift($flat_rate_costs);
// Loop through remaining "Flat rate" shipping methods to remove them all
foreach ( $flat_rate_costs as $key_rate => $cost){
unset($rates[$key_rate]);
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
You should need to refresh the shipping caches:
1) First ensure that the code is already saved on your function.php file.
2) In Shipping settings, enter in a Shipping Zone: Disable any Shipping Method and "save", then re-enable it and "save". You are done.

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+.
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.

Disable Free Shipping based on shipping classes in Woocommerce

I'm trying to write a function for WooCommerce that will disable free shipping if a product with a certain shipping class is present in the cart.
Here is what I have which is not working. e-packet is the shipping class that should disable free shipping if it is present in the cart.
function hide_shipping_when_class_is_in_cart( $rates, $package ) {
$shipping_classes = array('e-packet');
$if_exists = false;
foreach( $package['contents'] as $key => $values ) {
if( in_array( $values[ 'data' ]->get_shipping_class(), $shipping_classes ) )
$if_exists = true;
}
if( $if_exists ) unset( $rates['free_shipping:9'] );
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_class_is_in_cart', 10, 2 );
Based on similar: Unsetting WooCommerce shipping method based on cart items shipping classes
I have make very small changes. This code is tested and works (see the note at the end):
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_class_is_in_cart', 100, 2 );
function hide_shipping_when_class_is_in_cart( $rates, $package ) {
// Initialisation
$free_shipping_method = 'free_shipping:9';
$shipping_classes = array('e-packet');
$class_exists = false;
foreach( $package['contents'] as $cart_item )
if( in_array( $cart_item['data']->get_shipping_class(), $shipping_classes ) ) {
$class_exists = true;
break; // Stop the loop
}
if( $class_exists )
unset( $rates[$free_shipping_method] );
return $rates;
}
Code goes in function.php file of your active child theme (or active theme).
You should need to refresh the shipping caches:
1) First this code is already saved on your function.php file.
2) In Shipping settings, enter in a Shipping Zone and disable a Shipping Method and "save". Then re-enable that Shipping Method and "save". You are done.

Disable shipping method when a cart item has a specific shipping class?

I try to disable a shipping method if a specific shipping class is in the cart. I'm using the newest woocommerce version.
Below is my Code for my task.
It's placed at the end of my functions.php file of my Theme.
Sadly its not working.
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 = 513; // ID OF MY SHIPPING_CLASS
$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['flat_rate:2'] ); //VALUE:ID OF MY SHIPPING METHOD
}
return $rates;
}
I have tested simplifying a little your code (with the ids of my WC settings) and it works:
add_filter( 'woocommerce_package_rates', 'custom_hide_shipping_methods', 10, 2 );
function custom_hide_shipping_methods( $rates, $package ) {
foreach( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item[ 'data' ]; // The WC_Product object
$shipping_class_id = $product->get_shipping_class_id();
if( isset($rates['flat_rate:2']) && $shipping_class_id == 513 ) { // <== ID OF MY SHIPPING_CLASS
unset( $rates['flat_rate:2'] ); // Removing specific shipping method
break; // we stop the loop
}
}
return $rates;
}
So your code should work too (if you have set the correct IDs)
BUT you need (after saving your code to the function.php file of your active theme):
To remove all cart items that are remaining in cart when testing.
To refresh the shipping caches:
To do it, you can go in a shipping zone and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done.
Now you can test again and it should work

Categories