2

I am trying to enable free shipping for specific shipping zones (array) on selected days.

I'm using therefore this code:

add_filter( 'woocommerce_shipping_free_shipping_is_available', 'enable_free_shipping_on_selected_days', 10, 3 );
function enable_free_shipping_on_selected_days( $is_available, $package, $shipping_method ) {

    $shipping_zones = array('US, Europe');

        if ( array_key_exists( $shipping_zones, $rates ) && in_array( date( 'w' ), [ 6, 7 ] ) ) {
        return true;
    }
    return $is_available;
}

But I am getting an error: "Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, null given in.."

Any advice on how to make free shipping available for certain shipping zones on specific days of the week?

7uc1f3r
  • 28,449
  • 17
  • 32
  • 50

1 Answers1

1

$rates is not set in your code, hence the error message

To make free shipping available based on shipping zones and specific days of the week, you can use:

function filter_woocommerce_shipping_free_shipping_is_available( $available, $package, $shipping_method ) { 
    // The targeted shipping zones. Multiple can be entered, separated by a comma
    $shipping_zones = array( 'US', 'Europe', 'België' );
    
    // The targeted day numbers. 0 = Sunday, 1 = Monday.. to 6 for Saturday. Multiple can be entered, separated by a comma
    $day_numbers = array( 0, 1, 6 );

    // Message
    $notice = __( 'free shipping available', 'woocommerce' );
    
    /* END settings */
    
    // Default
    $available = false;
    
    // Get shipping zone
    $shipping_zone = wc_get_shipping_zone( $package );
    
    // Get the zone name
    $zone_name = $shipping_zone->get_zone_name();
    
    // Checks if a value exists in an array (zone name)
    if ( in_array( $zone_name, $shipping_zones ) ) {
        // Set the default timezone to use.
        date_default_timezone_set( 'UTC' );
        
        // Day number
        $day_number = date( 'w' );

        // Checks if a value exists in an array (day number)
        if ( in_array( $day_number, $day_numbers ) ) {
            // Clear all other notices          
            wc_clear_notices();
            
            // Display notice
            wc_add_notice( $notice, 'notice' );
            
            // True
            $available = true;      
        }
    }
 
    // Return
    return $available;
}
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'filter_woocommerce_shipping_free_shipping_is_available', 10, 3 );

// Optional: Hide other shipping methods when free shipping is available
function filter_woocommerce_package_rates( $rates, $package ) {
    // Empty array
    $free = array();

    // Loop trough
    foreach ( $rates as $rate_id => $rate ) {
        if ( $rate->method_id === 'free_shipping' ) {
            $free[ $rate_id ] = $rate;
            
            // Break loop
            break;
        }
    }
    
    return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );

Based on:

7uc1f3r
  • 28,449
  • 17
  • 32
  • 50
  • JMust one problem: I get double notices. –  Jun 06 '21 at 08:08
  • _"I get double notice"_. @HaroldAldersen, I can't reproduce the problem but I added some extra code that should prevent this from happening – 7uc1f3r Jun 06 '21 at 08:12