commerceguys/addressing

由 CLDR 和 Google 的地址数据驱动的地址库。

v2.2.2 2024-07-12 11:53 UTC

README

Build Status

一个 PHP 8.0+ 地址库,由 CLDR 和 Google 的地址数据驱动。

操作邮政地址,旨在识别精确的收件人位置,用于运输或账单目的。

特性

  • 支持超过 250 个地区的国家,由 CLDR v45 驱动。
  • 200 多个国家的地址格式
  • 60 个国家的子区域(行政区域、地区、从属地区)
  • 当相关时,同时提供拉丁语和本地子区域名称(例如:冲绳 / 沖縄縣)
  • 以 HTML 或纯文本格式进行格式化。
  • 通过 symfony/validator 进行验证
  • 区域

地址格式和子区域最初由 Google 的 地址数据服务 生成,现在由库拥有和维护。

还可以查看 commerceguys/intl 了解 CLDR 驱动的语言/货币/数字格式。

数据模型

地址接口 代表一个邮政地址,以下字段的获取器

  • 国家代码
  • 行政区域
  • 地区(城市)
  • 从属地区
  • 邮政编码
  • 排序代码
  • 地址行 1
  • 地址行 2
  • 地址行 3
  • 组织
  • 给定名称(名)
  • 附加名称(中间名/姓氏)
  • 姓氏(姓)

字段名称遵循 OASIS eXtensible Address Language (xAL) 标准。

该接口不假设可变。实现的应用程序可以扩展接口以提供设置器,或实现一个使用 PSR-7 风格 * mutators 或依赖于 AddressBuilder 的值对象。提供了一个默认的 地址值对象,可以用作示例,或由 Doctrine 映射(最好是作为可嵌入对象)。

地址格式 提供以下信息

  • 哪些字段被使用,以及顺序
  • 哪些字段是必需的
  • 哪些字段需要大写化以进行实际邮寄(便于自动排序邮件)
  • 行政区域(州、省、教区等)、地区(城市/邮镇/地区等)、从属地区(邻里、郊区、地区等)和邮政编码(邮政编码或 ZIP 编码)的标签
  • 验证邮政编码的正则表达式模式

国家 提供以下信息

  • 国家名称。
  • 数字和三位字母的国家代码。
  • 已知时的官方货币代码。
  • 国家跨越的时区。

子区域 提供以下信息

  • 子区域代码(用于在包裹/信封上表示子区域,例如 CA 代表加利福尼亚)
  • 子区域名称(在下拉菜单中显示给用户)
  • 如果国家使用非拉丁语脚本,则本地代码和名称(例如俄罗斯使用西里尔字母)。
  • 邮政编码模式(如果与地址格式不同)。

区域划分是分层的,最多可以有三个级别:行政区域 -> 地域 -> 从属地域。

use CommerceGuys\Addressing\AddressFormat\AddressFormatRepository;
use CommerceGuys\Addressing\Country\CountryRepository;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepository;

$countryRepository = new CountryRepository();
$addressFormatRepository = new AddressFormatRepository();
$subdivisionRepository = new SubdivisionRepository();

// Get the country list (countryCode => name), in French.
$countryList = $countryRepository->getList('fr-FR');

// Get the country object for Brazil.
$brazil = $countryRepository->get('BR');
echo $brazil->getThreeLetterCode(); // BRA
echo $brazil->getName(); // Brazil
echo $brazil->getCurrencyCode(); // BRL
print_r($brazil->getTimezones());

// Get all country objects.
$countries = $countryRepository->getAll();

// Get the address format for Brazil.
$addressFormat = $addressFormatRepository->get('BR');

// Get the subdivisions for Brazil.
$states = $subdivisionRepository->getAll(['BR']);
foreach ($states as $state) {
    $municipalities = $state->getChildren();
}

// Get the subdivisions for Brazilian state Ceará.
$municipalities = $subdivisionRepository->getAll(['BR', 'CE']);
foreach ($municipalities as $municipality) {
    echo $municipality->getName();
}

格式化器

地址格式化根据地址格式进行,可以是HTML或文本。

默认格式化器

格式化地址以供显示,总是添加本地化国家名称。

use CommerceGuys\Addressing\Address;
use CommerceGuys\Addressing\Formatter\DefaultFormatter;
use CommerceGuys\Addressing\AddressFormat\AddressFormatRepository;
use CommerceGuys\Addressing\Country\CountryRepository;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepository;

$addressFormatRepository = new AddressFormatRepository();
$countryRepository = new CountryRepository();
$subdivisionRepository = new SubdivisionRepository();
$formatter = new DefaultFormatter($addressFormatRepository, $countryRepository, $subdivisionRepository);
// Options passed to the constructor or format() allow turning off
// html rendering, customizing the wrapper element and its attributes.

$address = new Address();
$address = $address
    ->withCountryCode('US')
    ->withAdministrativeArea('CA')
    ->withLocality('Mountain View')
    ->withAddressLine1('1098 Alta Ave');

echo $formatter->format($address);

/** Output:
<p translate="no">
<span class="address-line1">1098 Alta Ave</span><br>
<span class="locality">Mountain View</span>, <span class="administrative-area">CA</span><br>
<span class="country">United States</span>
</p>
**/

邮政标签格式化器

负责将格式要求的大写字段进行大写处理(以便于自动化邮件分类)。

需要指定源国家代码,使其能够区分国内和国际邮件。在国内邮件的情况下,国家名称根本不显示。在国际邮件的情况下

  1. 邮政编码前缀与目的地邮政编码前缀。
  2. 将国家名称添加到格式化地址中,包括当前区域和英语。这符合万国邮政联盟的建议,以避免在过境国遇到困难。
use CommerceGuys\Addressing\Address;
use CommerceGuys\Addressing\Formatter\PostalLabelFormatter;
use CommerceGuys\Addressing\AddressFormat\AddressFormatRepository;
use CommerceGuys\Addressing\Country\CountryRepository;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepository;

$addressFormatRepository = new AddressFormatRepository();
$countryRepository = new CountryRepository();
$subdivisionRepository = new SubdivisionRepository();
// Defaults to text rendering. Requires passing the "origin_country"
// (e.g. 'FR') to the constructor or to format().
$formatter = new PostalLabelFormatter($addressFormatRepository, $countryRepository, $subdivisionRepository, ['locale' => 'fr']);

$address = new Address();
$address = $address
    ->withCountryCode('US')
    ->withAdministrativeArea('CA')
    ->withLocality('Mountain View')
    ->withAddressLine1('1098 Alta Ave');

echo $formatter->format($address, ['origin_country' => 'FR']);

/** Output:
1098 Alta Ave
MOUNTAIN VIEW, CA 94043
ÉTATS-UNIS - UNITED STATES
**/

验证器

地址验证依赖于Symfony验证器库。

执行检查

  • 所有必填字段都已填写。
  • 所有国家格式未使用的字段为空。
  • 所有区域都是有效的(值与预定义的区域匹配)。
  • 邮政编码是有效的(国家和区域级别的模式)。
use CommerceGuys\Addressing\Address;
use CommerceGuys\Addressing\Validator\Constraints\AddressFormatConstraint;
use CommerceGuys\Addressing\Validator\Constraints\CountryConstraint;
use Symfony\Component\Validator\Validation;

$address = new Address('FR');

$validator = Validation::createValidator();
// Validate the country code, then validate the rest of the address.
$violations = $validator->validate($address->getCountryCode(), new CountryConstraint());
if (!$violations->count()) {
  $violations = $validator->validate($address, new AddressFormatConstraint());
}

区域

区域是用于运输或税务目的的领土分组。例如,一组与区域关联的运输费率,只有当客户的地址属于该区域时,费率才可用。

区域可以匹配国家、区域(州/省/市),邮政编码。邮政编码也可以用范围或正则表达式表示。

区域示例

  • 加利福尼亚州和内华达州
  • 比利时、荷兰、卢森堡
  • 德国和一系列奥地利邮政编码(6691,6991,6992,6993)
  • 奥地利(不指定特定的邮政编码6691,6991,6992,6993)
use CommerceGuys\Addressing\Address;
use CommerceGuys\Addressing\Zone\Zone;

// Create the German VAT zone (Germany and 4 Austrian postal codes).
$zone = new Zone([
    'id' => 'german_vat',
    'label' => 'German VAT',
    'territories' => [
        ['country_code' => 'DE'],
        ['country_code' => 'AT', 'included_postal_codes' => '6691, 6991:6993'],
    ],
]);

// Check if the provided austrian address matches the German VAT zone.
$austrianAddress = new Address();
$austrianAddress = $austrianAddress
    ->withCountryCode('AT')
    ->withPostalCode('6992');
echo $zone->match($austrianAddress); // true

集成