Zones
The zones feature has been added in version
2.5.0
A zone represents a geographic area that can be composed of a set of countries and/or provinces.
This can be very useful when different rules apply depending on which zone an address is located in. Typical use cases for zones are:
- varying shipping fees;
- tax (VAT, Sales Tax) calculation;
- geographic pricing;
- GDPR-related extra content in EU countries.
Creating Zones
A zone can be created just by passing a name:
Zone::create(['name' => 'New York metropolitan area'])
Zone Scopes
Every zone has a scope, which can be one of the followings:
- shipping (default),
- billing,
- taxation,
- pricing,
- content.
The values come from the ZoneScope
enum,
that you can extend
in your application.
If no explicit scope is defined for the zone at creation, it will be the enum's
default value, i.e. shipping
out of the box.
Adding Zone Members
Countries and provinces can be added to zones as members.
Countries can be added via model object, or simply using their ids, which is their ISO 3166 code:
$eu = Zone::create(['name' => 'European Union']);
// Add one country via its country code:
$eu->addCountry('NL');
// Add one country using its model:
$germany = Country::find('DE');
$eu->addCountry($germany)
// Adding multiple countries via their codes:
$eu->addCountries('BE', 'FR', 'ES', 'PT', 'IT');
// Adding multiple countries via models:
$czechia = Country::find('CZ');
$slovakia = Country::find('SK');
$eu->addCountries($czechia, $slovakia);
Provinces can be added by passing their model objects:
$quebec = Province::findByCountryAndCode('CA', 'QC')
$ontario = Province::findByCountryAndCode('CA', 'ON')
$zone = Zone::create(['name' => 'Quebec-Ontario']);
$zone->addProvinces($quebec, $ontario);
Matching Zones
Checking a Country in a Zone
A zone can tell whether a country is part of it:
$centralEurope = Zone::create(['name' => 'Central Europe']);
$centralEurope->addCountries('DE', 'CZ', 'PL', 'SK', 'AT', 'HU', 'SI')
$centralEurope->isCountryPartOfIt('CZ');
// true
$centralEurope->isCountryPartOfIt('FR');
// false
Checking a Province in a Zone
Similarly, provinces can be checked against zones:
$brasov = Province::findByCountryAndCode('RO', 'BV');
$sibiu = Province::findByCountryAndCode('RO', 'SB');
$neamt = Province::findByCountryAndCode('RO', 'NT');
$transylvania = Zone::create(['name' => 'Transylvania']);
$transylvania->addProvinces($brasov, $sibiu);
$transylvania->isProvincePartOfIt($sibiu);
// true
$transylvania->isProvincePartOfIt($brasov);
// true
$transylvania->isProvincePartOfIt($neamt);
// false
Checking if an Address is in a Zone
Addresses - if their country or their province is part of a zone - can be checked if they're in a zone.
$centralMacedoniaRegion = Province::create([
'country_id' => 'GR',
'name' => 'Central Macedonia',
'code' => 'B',
'type' => ProvinceType::REGION,
]);
$ancientMacedonia = Zone::create(['name' => 'Macedonia (ancient)']);
$ancientMacedonia->addCountry('MK');
$ancientMacedonia->addProvince($centralMacedoniaRegion);
$addressInNorthMacedonia = Address::create([
'country_id' => 'MK',
'city' => 'Skopje',
'address' => 'Boulevard Goce Delchev 5',
]);
$addressInThessaloniki = Address::create([
'country_id' => 'GR',
'city' => 'Thessaloniki',
'province_id' => $centralMacedoniaRegion
'address' => 'Protomagias 25',
]);
$ancientMacedonia->isAddressPartOfIt($addressInNorthMacedonia);
//true
$ancientMacedonia->isAddressPartOfIt($addressInThessaloniki);
//true
Finding Zones for Addresses, Provinces and Countries
To find the zones an address, province or country belongs to, use the Zones
utility that simplifies querying zones.
Zones::withAnyScope()->theCountryBelongsTo('IN');
// Collection of `Zone` models
It is also possible to return zones with a specific scope.
$bavaria = Province::findByCountryAndCode('DE', 'BY')
Zone::create(['name' => 'South East Germany', 'scope' => ZoneScope::SHIPPING])->addProvince($bavaria);
Zones::withShippingScope()->theProvinceBelongsTo($bavaria);
// Illuminate\Database\Eloquent\Collection
// #items: array:1 [
// 0 => Konekt\Address\Models\Zone
// #attributes: array:5 [
// "id" => 1
// "name" => "South East Germany"
// "scope" => "shipping"
// ]
// Querying for another scope
Zones::withBillingScope()->theProvinceBelongsTo($bavaria);
// empty Collection
$addressInSweden = Address::create(['country_id' => 'SE', 'city' => 'BorĂ¥s', 'name' => 'Antoinette Suromy', 'address' => 'Gustav Adolfsgatan 500', 'postalcode' => '500 00']);
$scandinavia = Zone::create(['name' => 'Scandinavia', 'scope' => ZoneScope::PRICING]);
$scandinavia->addCountries('SE', 'FI', 'DK', 'NO');
Zones::withPricingScope()->theAddressBelongsTo($addressInSweden);
// Illuminate\Database\Eloquent\Collection
// #items: array:1 [
// 0 => Konekt\Address\Models\Zone
// #attributes: array:5 [
// "id" => 1
// "name" => "Scandinavia"
// "scope" => "pricing"
// ]
Zones::withTaxationScope()->theAddressBelongsTo($addressInSweden);
// empty Collection