5
votes

I recently updated to WooCommerce 2.6 on my shop and they have updated their shipping system. Before I used this to hide the paid shipping option when an specific order value was reached and free shipping was triggered:

/**
 * woocommerce_package_rates is a 2.1+ hook
 */
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );

/**
 * Hide shipping rates when free shipping is available
 *
 * @param array $rates Array of rates found for the package
 * @param array $package The package array/object being shipped
 * @return array of modified rates
 */
function hide_shipping_when_free_is_available( $rates, $package ) {

    // Only modify rates if free_shipping is present
    if ( isset( $rates['free_shipping'] ) ) {

        // 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;
}

Although this does not work anymore. I need a new fix and im not really into coding.

Does anyone have a solution to this?

The above solution was from this site:
Hide other shipping methods when FREE SHIPPING is available

I'm guessing that some parameters have changed since they updated the shipping methods.

I hope some one out there knows how to fix this.

3

3 Answers

3
votes

Please try replacing your existing snippet with the below one. Details of this snippet is described in this article. Let me know if this can be improved.

add_filter('woocommerce_package_rates', 'xa_hide_shipping_rates_when_free_is_available', 10, 2);

function xa_hide_shipping_rates_when_free_is_available($rates, $package)
{
    global $woocommerce;
    $version = "2.6";
    if (version_compare($woocommerce->version, $version, ">=")) {
        foreach($rates as $key => $value) {
            $key_part = explode(":", $key);
            $method_title = $key_part[0];
            if ('free_shipping' == $method_title) {
                $free_shipping = $rates[$key];
                // Unset all rates.
                $rates = array();
                // Restore free shipping rate.
                $rates[$key] = $free_shipping;
                return $rates;
            }
        }
    }
    else {
        if (isset($rates['free_shipping'])) {
          // Below code is for unsetting single shipping method/option.
            // unset($rates['flat_rate']);
            $free_shipping = $rates['free_shipping'];
            // Unset all rates.
            $rates = array();
            // Restore free shipping rate.
            $rates['free_shipping'] = $free_shipping;
        }
    }

    return $rates;
}
1
votes

Provided you have removed the legacy shipping methods (shipping methods must be set up using new shipping zones), you can use the following snippet to remove all other shipping methods when free shipping is available. (WooCommerce 2.6+):

  /**
   * 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 ); 

From the updated docs

0
votes

Ok the following code will allow Local Pickup with Free Shipping:

// ##### WOOCOMMERCE - HIDE OTHER SHIPPING METHODS WHEN FREE SHIPPING IS AVAILABLE #####
add_filter('woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2);
function hide_shipping_when_free_is_available($rates, $package) {
    $free_yn = 0;
    $pickup_yn = 0;
    foreach($rates as $key => $value) {
        $key_part = explode(":", $key);
        $method_title = $key_part[0];
        if ('free_shipping' == $method_title) {
            // check if free shipping rate exists
            $free_yn = 1;
            $free_shipping = $rates[$key];
            $free_key = $key;
        }
        if ('local_pickup' == $method_title) {
            // check if local pickup rate exists
            $pickup_yn = 1;
            $local_pickup = $rates[$key];
            $pickup_key = $key;
        }
    }
    if ($free_yn == 1) {
        // Unset all rates.
        $rates = array();
        // Restore free shipping rate.
        $rates[$free_key] = $free_shipping;
        if ($pickup_yn == 1) {
            // Restore local pickup rate.
            $rates[$pickup_key] = $local_pickup;
        }
        return $rates;
    }
    return $rates;
}