On the template for choosing shipping method, I need to be able to remove/hide some shipping methods from being shown, based on the shipping zone that has been set by Craft, which is based on the address entered, etc.

I'm using Postie for live Fedex rates, along with a couple of custom shipping methods, but Postie adds its live rates to the array of shipping methods regardless of the shipping zone, so I end up with my custom method, plus the Fedex methods, when I just want the custom one.

I'd like to evaluate shippingZone that is set for this cart, and if it is zone A or B, not how any Fedex methods, else, show them. I just need access to the shippingZone to do this.

Like so: https://d.pr/i/JCmTiT

Any way to get it?


If postie plugin can't add zone support, then you will need to limit the selections options on the front end and need the zones available in twig.

Postie implementing it would be the first preferance, as there would be no backend validation if you just hid the options in twig.

There currently is no craft.commmerce.shippingZones twig variable. You would need to expose it with a plugin.

Creating a plugin at the http://pluginfactory.io with a variable class.

To the variable class within the plugin add:

public function getAllShippingZones()
  return craft()->commerce_shippingZones->getAllShippingZones();

public function matchZoneAndAddress($zone, Commerce_AddressModel $address)
    if ($zone->countryBased)
        $countryIds = $zone->getCountryIds();

        if (in_array($address->countryId, $countryIds))
            return true;
        $states = [];
        $countries = [];
        $stateAbbrs = [];
        $stateNames = [];
        foreach ($zone->states as $state)
            $states[] = $state->id;
            $stateNames[] = $state->name;
            $stateAbbrs[] = $state->abbreviation;
            $countries[] = $state->countryId;

        if ($countries){
        if ($stateNames){
        if ($stateAbbrs){

        $countryAndStateMatch = (in_array($address->countryId, $countries) && in_array($address->stateId, $states));
        $countryAndStateNameMatch = (in_array($address->countryId, $countries) && $this->_inArrayCaseinsensitive($address->getStateText(), $stateNames));
        $countryAndStateAbbrMatch = (in_array($address->countryId, $countries) && $this->_inArrayCaseinsensitive($address->getStateAbbreviation(), $stateAbbrs));

        if ($countryAndStateMatch || $countryAndStateNameMatch || $countryAndStateAbbrMatch)
            return true;

    return false;

 * @param $needle
 * @param $haystack
 * @return bool
private function _inArrayCaseinsensitive($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack), false);

This would allow you to do:

{% set doesMatch = craft.yourPlugin.matchZoneAndAddress(zone, cart.shippingAddress) %}

To determine if an address is within a zone.

Hope that helps.

|improve this answer|||||
  • This definitely got me on the right track. I appreciate the help. – Chad Crowell Mar 21 '18 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.