Search code examples
phpwordpressdatewoocommerceshipping-method

Make free shipping available for certain shipping zones on specific days of the week in WooCommerce


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?


Solution

  • $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: