Make free shipping available on specific days of the week in WooCommerce - php

I'm looking for a way to give free shipping on all orders based on weekday of the order. So if someone places an order (let's say on Monday) it will give him free shipping no matter what type of order quantity/amount/etc.
I've tried to hook up something from different other tutorials but I can't seem to get the part where I change the free_shipping limit + not sure it works since it's incomplete.
function free_shipping_day( $rates, $package ) {
// valid days
$valid_days = array('Mon');
// current day
$today = date ( 'D' );
// check if it's valid day
if( in_array($today, $valid_day) ){
// clear other shipping methods allow only free
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
}
}
// set free_shipping limit to 0
// show notice
wc_add_notice( __( "Shipping is free today!" ), 'notice');
}
}
add_action('woocommerce_package_rates', 'free_shipping_day');
Any help is very appreciated since I'm kind of stuck with this.

To make free shipping available on specific days of the week, it requires a different hook to bypass the free shipping limitations (if they exist).
We use date() function with "w" parameter that gives an integer from 0 (Sunday) to 6 (Saturday):
// Enable free shipping on specific days of the week
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'enable_free_shipping_for_specific_week_days', 10, 3 );
function enable_free_shipping_for_specific_week_days( $is_available, $package, $shipping_method ) {
// Free shipping is available on mondays and wednesdays for example
if( in_array( date('w'), [ 1, 3 ] ) ) {
return true;
}
return $is_available;
}
To hide other shipping methods when free shipping is available, you can use additionally the following:
// Hide other shipping methods when free shipping is available
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_methods_when_free_shipping_is_available', 100, 2 );
function hide_other_shipping_methods_when_free_shipping_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;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Add the follows code snippet in your active theme's functions.php -
function enable_free_shipping_for_days( $rates ) {
$free = array();
// valid days
$valid_days = array('Mon');
if( !in_array( date('D'), $valid_days ) ) return $rates;
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' !== $rate->method_id ) continue;
$free[ $rate_id ] = $rate;
}
if( $free ) wc_add_notice( __( "Shipping is free today!" ), 'notice');
return ( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'enable_free_shipping_for_days', 99 );

Related

How can I change the shipping class to flat shipping? (woocommerce)

I'm working on hiding free shipping when there is a fixed price shipping amount based on certain products. This code is working and after certain sum is also disabled. But I want this to work with flat shipping conditional, not post class conditional.
I want it: if ( isset( $rates['flat_rate:1'] ) )
But it works: if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target )
add_filter( 'woocommerce_package_rates', 'bbloomer_hide_free_shipping_for_shipping_class', 9999, 2 );
function bbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$shipping_class_target = 261; // shipping class ID (to find it, see screenshot below)
$subtotal = WC()->cart->get_subtotal();
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target && $subtotal <= 299 ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset( $rates['free_shipping:2'] ); // shipping method with ID (to find it, see screenshot below)
}
return $rates;
}

Enable only free shipping method for a specific custom field value in Woocommerce

I'm trying to add code like the one below into functions.php file. The overall function is to check products in cart and their custom fields (post_meta) called auto_delivery_default.
If its certain text in the custom field then display free shipping only, if all other text then show all other shipping methods.
Here's what I've gotten so far but I'm overlooking something making it not function right;
function show_free_ship_to_autodelivery ( $autodelivery_rate ) {
$autodelivery_free = array();
foreach( WC()->cart->get_cart() as $cart_item ){
$product = $cart_item['data'];
$product_id = $product->get_id(); // get the product ID
$autodelivery = get_post_meta( $product->get_id(), 'auto_delivery_default', true );
if( $autodelivery == "90 Days" ) {
$autodeliveryfree = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$autodelivery_free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $autodelivery_free ) ? $autodelivery_free : $autodelivery_rate;
}
}
}
add_filter( 'woocommerce_package_rates', 'show_free_ship_to_autodelivery', 10);
There is some errors and mistakes in your code… Instead, try the following that will hide other shipping methods when free shipping is available and when a cart item with a custom field auto_delivery_default has a value of 90 Days:
add_filter( 'woocommerce_package_rates', 'show_only_free_shipping_for_autodelivery', 100, 2 );
function show_only_free_shipping_for_autodelivery ( $rates, $package ) {
// Loop through cart items
foreach( $package['contents'] as $cart_item ){
if( $cart_item['data']->get_meta('auto_delivery_default') == '90 Days' ) {
$found = true;
break; // Stop the loop
}
}
if( ! ( isset($found) && $found ) )
return $rates; // Exit
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Change displayed Free shipping label when Free shipping is enabled in Woocommerce

I am using this official woocommerce hook and snippet to Hide other shipping methods when “Free Shipping” is triggered by a coupon. Which works fine.
Currnently, it just displays FREE SHIPPING. I am trying to add in a text line where it displays FREE SHIPPING to say "-£3.95" in order to let the user know that they have saved money off their shipping.
I have tried adding a dummy "fee" inline to the IF statement, but it wont display.
$cart->add_fee( 'You saved -£3.95');
Code is as follows:
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
e.g. like the following example:
There is 2 ways:
1) In your existing code (best way) - It will append your formatted saved price on free shipping:
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_when_free_is_available', 100, 1 );
function hide_other_shipping_when_free_is_available( $rates ) {
// Here set your saved amount
$labeleld_price = -3.95;
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
// Here we append the labbelled saved price formated display
$free[ $rate_id ]->label .= ' (' . strip_tags( wc_price( $labeleld_price ) ) . ')';
break; // stop the loop
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of your active child theme (or active theme). tested and works.
2) Using settings - Renaming the "Free shipping" label method:

Hide other shipping options when Free shipping is available for one zone only in Woocommerce

I need a way to achieve the following: If Free Shipping is available, AND the order is being shipped to a specific zone, hide all other shipping methods.
I found this snippet:
function hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 100 );
How would I add a conditional into it to only apply it to orders going to one zone?
The following code will hide all other shipping methods when free shipping is available for a specific Zone (you will define in the function the targeted zone ID or Zone name):
add_filter( 'woocommerce_package_rates', 'free_shipping_hide_others_by_zone', 100, 2 );
function free_shipping_hide_others_by_zone( $rates, $package ) {
// HERE define your shipping zone ID OR the shipping zone name
$defined_zone_id = '';
$defined_zone_name = 'Europe';
// Get The current WC_Shipping_Zone Object
$zone = WC_Shipping_Zones::get_zone_matching_package( $package );
$zone_id = $zone->get_id(); // The zone ID
$zone_name = $zone->get_zone_name(); // The zone name
$free = array(); // Initializing
// Loop through shipping rates
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id && ( $zone_id == $defined_zone_id || $zone_name == $defined_zone_name ) ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
Code goes in function.php file of the active child theme (or active theme). Tested and work.
/**
* Hide shipping rates when free shipping is available.
* Updated to support WooCommerce 2.6 Shipping Zones.
*
* #param array $rates Array of rates found for the package.
* #return array
*/
function my_hide_shipping_when_free_is_available( $rates ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );

WooCommerce Free Shipping if over 5 pounds

I'm trying to write a function that will offer free shipping only (remove all other options) if the order is over 5 pounds (80 ounces), but it doesn't work although the code seems correct.
This is what I have:
// Hide ALL shipping options but FREe when over 80 ounches (5 pounds)
add_filter( 'woocommerce_available_shipping_methods', 'ship_free_if_over_five_pounds' , 10, 1 );
/**
* Hide ALL Shipping option but free if over 5 pounds
*
* #param array $available_methods
*/
function ship_free_if_over_five_pounds( $available_methods ) {
global $woocommerce;
$whats_the_weight = $woocommerce->cart->cart_contents_weight;
if($whats_the_weight != 80) :
// Get Free Shipping array into a new array
$freeshipping = array();
$freeshipping = $available_methods['free_shipping'];
// Empty the $available_methods array
unset( $available_methods );
// Add Free Shipping back into $avaialble_methods
$available_methods = array();
$available_methods[] = $freeshipping;
endif;
return $available_methods;
}
Any thoughts?
The code is based on example #19 on this site: My 25 Best WooCommerce Snippets For WordPress Part 2
I know that this is an old question, but I have this recent alternative…
First, in your code "if the order is over 5 pounds (80 ounces)" your if statement should be if($whats_the_weight > 80) instead of !=… But i think that your code is a little outdated if you use WooCommerce 2.6+.
After instead using global $woocommerce; with $woocommerce->cart->cart_contents_weight; you could use: WC()->cart->cart_contents_weight;
I have this much more recent code snippet based on this official thread for WooCommerce 2.6+. You should try it:
add_filter( 'woocommerce_package_rates', 'my_hide_shipping_when_free_is_available', 100 );
function my_hide_shipping_when_free_is_available( $rates ) {
$cart_weight = WC()->cart->cart_contents_weight; // Cart total weight
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id && $cart_weight > 80 ) { // <= your weight condition
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
}
For WooCommerce 2.5, You should try this:
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
function hide_shipping_when_free_is_available( $rates, $package ) {
$cart_weight = WC()->cart->cart_contents_weight; // Cart total weight
// Only modify rates if free_shipping is present
if ( isset( $rates['free_shipping'] ) && $cart_weight > 80 ) { // Here your weight condition
// To unset a single rate/method, do the following. This example unsets flat_rate shipping
unset( $rates['flat_rate'] );
// To unset all methods except for free_shipping, do the following
$free_shipping = $rates['free_shipping'];
$rates = array();
$rates['free_shipping'] = $free_shipping;
}
return $rates;
}
I've made an plugin where you can set the maximum weight for free shipping!
Take an look at: http://wordpress.org/plugins/woocommerce-advanced-free-shipping/

Categories