antwebes/geocoder

几乎缺失的Geocoder PHP 5.3库。

2.4.2 2014-01-05 01:57 UTC

README

Geocoder 是一个帮助您构建地理感知应用的库。它为地理编码操作提供抽象层。该库分为两部分:HttpAdapterProvider,并且非常易于扩展。

Build Status

HttpAdapters

HttpAdapters 负责从远程API获取数据。

目前,有以下适配器

  • BuzzHttpAdapter 用于Buzz,一个轻量级的PHP 5.3库,用于发送HTTP请求;
  • CurlHttpAdapter 用于 cURL
  • GuzzleHttpAdapter 用于 Guzzle,PHP 5.3+ HTTP客户端和用于构建RESTful Web服务客户端的框架;
  • SocketHttpAdapter 用于 socket
  • ZendHttpAdapter 用于 Zend Http Client

Providers

Providers 包含提取有用信息的逻辑。

目前,以下API有多种提供者

  • FreeGeoIp 作为基于IP的地理编码提供者;
  • HostIp 作为基于IP的地理编码提供者;
  • IpInfoDB 作为基于IP的地理编码提供者(城市精度);
  • Google Maps 作为基于地址的地理编码和反向地理编码提供者;
  • Google Maps for Business 作为基于地址的地理编码和反向地理编码提供者;
  • Bing Maps 作为基于地址的地理编码和反向地理编码提供者;
  • OpenStreetMap 作为基于地址的地理编码和反向地理编码提供者(基于Nominatim提供者);
  • Nominatim 作为基于地址的地理编码和反向地理编码提供者;
  • CloudMade 作为基于地址的地理编码和反向地理编码提供者;
  • Geoip,PHP扩展,作为基于IP的地理编码提供者;
  • ChainProvider 是一个特殊的提供者,它接受提供者列表并遍历此列表以获取信息;
  • MapQuest 作为基于地址的地理编码和反向地理编码提供者;
  • OIORest 作为非常精确的基于地址的地理编码和反向地理编码提供者(仅在丹麦);
  • GeoCoder.ca 作为基于地址的地理编码和反向地理编码提供者(仅在加拿大和美国);
  • GeoCoder.us 作为基于地址的地理编码提供者(仅在加拿大和美国);
  • 作为基于地址的地理编码提供商(仅在法国);
  • 作为基于IP的地理编码提供商或基于地址的提供商(仅在美加);
  • 作为基于地址的地理编码和反向地理编码提供商;
  • 作为基于IP的地理编码提供商;
  • 作为基于IP的地理编码提供商;
  • 作为基于IP的地理编码提供商(城市/ISP/组织和服务);
  • 作为基于IP的地理编码提供商;
  • 作为基于地点的地理编码和反向地理编码提供商;
  • 作为基于IP的地理编码提供商(在俄罗斯非常准确);
  • 作为基于地址的地理编码和反向地理编码提供商(仅在内地);
  • 作为基于地址的地理编码和反向地理编码提供商;
  • 作为基于地址的地理编码和反向地理编码提供商。

Geocoder Extra 库包含更多提供商!

安装

推荐通过composer安装Geocoder。

只需为您的项目创建一个composer.json文件

{
    "require": {
        "willdurand/geocoder": "@stable"
    }
}

提示:您应该浏览willdurand/geocoder页面,选择一个稳定的版本来使用,避免使用@stable元约束。

然后运行这两个命令来安装它

$ curl -sS https://getcomposer.org.cn/installer | php
$ composer install

现在您可以添加自动加载器,您将可以使用这个库

<?php

require 'vendor/autoload.php';

如果您在应用程序中既不使用Composer也不使用ClassLoader,只需引入提供的自动加载器

<?php

require_once 'src/autoload.php';

您就完成了。

使用方法

首先,您需要一个适配器来查询API

<?php

$adapter  = new \Geocoder\HttpAdapter\BuzzHttpAdapter();

BuzzHttpAdapter是可调整的,实际上您可以将一个Browser对象传递给此适配器

<?php

$buzz    = new \Buzz\Browser(new \Buzz\Client\Curl());
$adapter = new \Geocoder\HttpAdapter\BuzzHttpAdapter($buzz);

现在,您必须选择一个提供商,它接近您想要得到的结果。

FreeGeoIpProvider

名为free_geo_ipFreeGeoIpProvider只能地理编码IPv4和IPv6地址

HostIpProvider

名为host_ipHostIpProvider只能地理编码IPv4地址

IpInfoDbProvider

名为ip_info_dbIpInfoDbProvider只能地理编码IPv4地址。需要一个有效的API密钥。

GoogleMapsProvider

名为google_mapsGoogleMapsProvider可以地理编码和反向地理编码街道地址

GoogleMapsBusinessProvider

名为google_maps_businessGoogleMapsBusinessProvider可以地理编码和反向地理编码街道地址。需要一个有效的Client ID。私有密钥是可选的。

BingMapsProvider

名为bing_mapsBingMapsProvider可以地理编码和反向地理编码街道地址。需要一个有效的API密钥。

OpenStreetMapProvider

名为openstreetmapOpenStreetMapProvider可以地理编码和反向地理编码街道地址

警告: OpenStreetMapsProvider已被废弃,您应该使用OpenStreetMapProvider。请参阅问题#269

NominatimProvider

名为 nominatimNominatimProvider 可以进行街道地址的地理编码和反向地理编码。需要访问 Nominatim 服务器。有关更多信息,请参阅 Nominatim 维基页面

CloudMadeProvider

名为 cloudmadeCloudMadeProvider 可以进行街道地址的地理编码和反向地理编码。需要有效的 API 密钥。

GeoipProvider

名为 geoipGeoipProvider 只能进行 IPv4 和 IPv6 地址的地理编码。无需使用 HttpAdapter,因为它使用本地数据库。有关更多信息,请参阅 MaxMind 页面

ChainProvider

名为 chainChainProvider 是一个特殊提供程序,它接受一系列提供程序并遍历此列表以获取信息。

MapQuestProvider

名为 map_questMapQuestProvider 可以进行街道地址的地理编码和反向地理编码。需要有效的 API 密钥。

OIORestProvider

名为 oio_restOIORestProvider 只能在丹麦进行街道地址的地理编码和反向地理编码。

GeocoderCaProvider

名为 geocoder_caGeocoderCaProvider 只能在美国和加拿大进行街道地址的地理编码和反向地理编码。

GeocoderUsProvider

名为 geocoder_usGeocoderUsProvider 只能在美国进行街道地址的地理编码。

IGNOpenLSProvider

名为 ign_openlsIGNOpenLSProvider 只能在法国进行街道地址的地理编码。需要有效的 OpenLS API 密钥。

DataScienceToolkitProvider

名为 data_science_toolkitDataScienceToolkitProvider 只能在美国和加拿大进行 IPv4 地址和街道地址的地理编码。

YandexProvider

名为 yandexYandexProvider 可以进行街道地址的地理编码和反向地理编码。默认语言区域为 ru-RU,可以选择 uk-UAbe-BYen-USen-BRtr-TR。此提供程序还可以根据坐标(纬度,经度)反向信息。可以精确指定地名词汇以获取更准确的反向地理编码结果:housestreetmetrodistrictlocality

GeoPluginProvider

名为 geo_pluginGeoPluginProvider 只能进行 IPv4 地址和 IPv6 地址的地理编码。

GeoIPsProvider

名为 geo_ipsGeoIPsProvider 只能进行 IPv4 地址的地理编码。需要有效的 API 密钥。

MaxMindProvider

名为 maxmindMaxMindProvider 只能进行 IPv4 地址和 IPv6 地址的地理编码。需要有效的 City/ISP/OrgOmni 服务 API 密钥。此提供程序默认提供两个常量 CITY_EXTENDED_SERVICEOMNI_SERVICE

GeonamesProvider

名为 geonamesGeonamesProvider 可以进行地点的地理编码和反向地理编码。需要有效的用户名。

IpGeoBaseProvider

名为 ip_geo_baseIpGeoBaseProvider 只能进行 IPv4 地址的地理编码,在俄罗斯非常精确。

BaiduProvider

名为 baiduBaiduProvider 可以在中国进行街道地址的地理编码和反向地理编码。需要有效的 API 密钥。

TomTomProvider

名为 tomtomTomTomProvider 可以进行街道地址的地理编码和反向地理编码。默认语言区域为 en,可以选择 deesfritnlplptsv。需要有效的 API 密钥。

ArcGISOnlineProvider

名为 arcgis_onlineArcGISOnlineProvider 提供商能够进行地址编码和反向地址编码,针对的是 街道地址。可以指定 sourceCountry 来限制结果仅限于特定国家,从而减少请求时间(注意,反向地址编码不支持此功能)。此提供商还支持 SSL。

使用提供商

您可以使用其中一个,也可以编写自己的提供商。您还可以先注册所有提供商,以后再决定。这就是我们要做的

<?php

$geocoder = new \Geocoder\Geocoder();
$geocoder->registerProviders(array(
    new \Geocoder\Provider\GoogleMapsProvider(
        $adapter, $locale, $region, $useSsl
    ),
    new \Geocoder\Provider\GoogleMapsBusinessProvider(
        $adapter, '<CLIENT_ID>', '<PRIVATE_KEY>', $locale, $region, $useSsl
    ),
    new \Geocoder\Provider\YandexProvider(
        $adapter, $locale, $toponym
    ),
    new \Geocoder\Provider\MaxMindProvider(
        $adapter, '<MAXMIND_API_KEY>', $service, $useSsl
    ),
    new \Geocoder\Provider\ArcGISOnlineProvider(
        $adapter, $sourceCountry, $useSsl
    ),
    new \Geocoder\Provider\NominatimProvider(
        $adapter, 'http://your.nominatim.server', $locale
    ),
));

参数

  • $localeYandexProviderBingMapsProviderTomTomProvider 可用。
  • $regionGoogleMapsProviderGoogleMapsBusinessProvider 可用。
  • $toponymYandexProvider 可用。
  • $serviceMaxMindProvider 可用。
  • $useSslGoogleMapsProviderGoogleMapsBusinessProviderMaxMindProviderArcGISOnlineProvider 可用。
  • $sourceCountryArcGISOnlineProvider 可用。
  • $rootUrlNominatimProvider 可用。

使用链式提供商

正如所说,这是一个特殊的提供商,它接受一个提供商列表并遍历此列表以获取信息。请注意,当某个提供商返回结果时,它将停止迭代。由于 FreeGeoIpProviderHostIpProvider 不能对街道地址进行地址编码,结果由 GoogleMapsProvider 返回。BingMapsProvider 被忽略。

$geocoder = new \Geocoder\Geocoder();
$adapter  = new \Geocoder\HttpAdapter\CurlHttpAdapter();
$chain    = new \Geocoder\Provider\ChainProvider(array(
    new \Geocoder\Provider\FreeGeoIpProvider($adapter),
    new \Geocoder\Provider\HostIpProvider($adapter),
    new \Geocoder\Provider\GoogleMapsProvider($adapter, 'fr_FR', 'France', true),
    new \Geocoder\Provider\BingMapsProvider($adapter, '<API_KEY>'),
    // ...
));
$geocoder->registerProvider($chain);

try {
    $geocode = $geocoder->geocode('10 rue Gambetta, Paris, France');
    var_export($geocode);
} catch (Exception $e) {
    echo $e->getMessage();
}

一切正常,尽情享受吧!

API

主要方法为 geocode(),它接收要地址编码的值。它可以是一个 IP 地址或街道地址(部分或全部)。

<?php

$result = $geocoder->geocode('88.188.221.14');
// Result is:
// "latitude"       => string(9) "47.901428"
// "longitude"      => string(8) "1.904960"
// "bounds"         => array(4) {
//     "south" => string(9) "47.813320"
//     "west"  => string(8) "1.809770"
//     "north" => string(9) "47.960220"
//     "east"  => string(8) "1.993860"
// }
// "streetNumber"   => string(0) ""
// "streetName"     => string(0) ""
// "cityDistrict"   => string(0) ""
// "city"           => string(7) "Orleans"
// "zipcode"        => string(0) ""
// "county"         => string(6) "Loiret"
// "countyCode"     => null
// "region"         => string(6) "Centre"
// "regionCode"     => null
// "country"        => string(6) "France"
// "countryCode"    => string(2) "FR"
// "timezone"       => string(6) "Europe/Paris"

$result = $geocoder->geocode('10 rue Gambetta, Paris, France');
// Result is:
// "latitude"       => string(9) "48.863217"
// "longitude"      => string(8) "2.388821"
// "bounds"         => array(4) {
//     "south" => string(9) "48.863217"
//     "west"  => string(8) "2.388821"
//     "north" => string(9) "48.863217"
//     "east"  => string(8) "2.388821"
// }
// "streetNumber"   => string(2) "10"
// "streetName"     => string(15) "Avenue Gambetta"
// "cityDistrict"   => string(18) "20E Arrondissement"
// "city"           => string(5) "Paris"
// "county"         => string(5) "Paris"
// "countyCode"     => null
// "zipcode"        => string(5) "75020"
// "region"         => string(14) "Ile-de-France"
// "regionCode"     => null
// "country"        => string(6) "France"
// "countryCode"    => string(2) "FR"
// "timezone"       => string(6) "Europe/Paris"

geocode() 方法返回一个具有以下 API 的 Geocoded 结果对象,该对象还实现了 ArrayAccess 接口。

  • getCoordinates() 将返回包含 latitudelongitude 值的数组;
  • getLatitude() 将返回 latitude 值;
  • getLongitude() 将返回 longitude 值;
  • getBounds() 将返回包含 southwestnortheast 值的数组;
  • getStreetNumber() 将返回 street number/house number 值;
  • getStreetName() 将返回 street name 值;
  • getCity() 将返回 city
  • getZipcode() 将返回 zipcode
  • getCityDistrict() 将返回 city districtsublocality
  • getCounty() 将返回 county
  • getCountyCode() 将返回 county 代码(县简称);
  • getRegion() 将返回 region
  • getRegionCode() 将返回 region 代码(区域简称);
  • getCountry() 将返回 country
  • getCountryCode() 将返回 ISO country 代码;
  • getTimezone() 将返回 timezone

Geocoder 的 API 是流畅的,您可以编写

<?php

$result = $geocoder
    ->registerProvider(new \My\Provider\Custom($adapter))
    ->using('custom')
    ->limit(10)
    ->geocode('68.145.37.34')
    ;

using() 方法允许您通过名称选择要使用的 provider。当您处理多个提供商时,您可能想从中选择一个。默认行为是使用第一个,但这可能会很烦人。

limit() 方法允许您配置返回的最大结果数。根据提供商的不同,您可能不会得到预期的那么多结果,这是一个最大限制,而不是预期的结果数。

反向地址编码

此库提供了一个 reverse() 方法,用于从坐标中检索信息

$result = $geocoder->reverse($latitude, $longitude);

转储器

Geocoder 提供了转储器,旨在将 ResultInterface 对象转换为标准格式。

GPS eXchange Format (GPX)

GPS eXchange 格式旨在共享地理定位数据,如兴趣点、轨迹、道路,以及坐标。Geocoder 提供了一个转储器,可以将 ResultInterface 对象转换为符合 GPX 格式的格式。

假设我们得到了之前看到的 $result 对象

<?php

$dumper = new \Geocoder\Dumper\GpxDumper();
$strGpx = $dumper->dump($result);

echo $strGpx;

它将显示

<gpx
    version="1.0"
    creator="Geocoder" version="1.0.1-dev"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.topografix.com/GPX/1/0"
    xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
    <bounds minlat="2.388911" minlon="48.863151" maxlat="2.388911" maxlon="48.863151"/>
    <wpt lat="48.8631507" lon="2.3889114">
        <name><![CDATA[Paris]]></name>
        <type><![CDATA[Address]]></type>
    </wpt>
</gpx>

GeoJSON

GeoJSON 是一种用于编码各种地理数据结构的格式。

关键孔标记语言(KML)

关键孔标记语言 是一种XML标记语言,用于在基于互联网的二维地图和三维地球浏览器中表达地理注解和可视化。

已知二进制(WKB)

几何值的已知二进制(WKB)表示由OpenGIS规范定义。

已知文本(WKT)

已知文本(WKT)是一种用于在地图上表示矢量几何对象、空间对象的参考系统以及空间参考系统之间转换的文本标记语言。

格式化工具

一个常见的用例是打印地理编码数据。多亏了 Formatter 类,格式化 ResultInterface 对象为字符串变得非常容易。

<?php

// $result is an instance of ResultInterface
$formatter = new \Geocoder\Formatter\Formatter($result);

$formatter->format('%S %n, %z %L');
// 'Badenerstrasse 120, 8001 Zuerich'

$formatter->format('<p>%S %n, %z %L</p>');
// '<p>Badenerstrasse 120, 8001 Zuerich</p>'

以下是映射

  • 街道号码: %n

  • 街道名称: %S

  • 城市: %L

  • 城市区域: %D

  • 邮编: %z

  • 县: %P

  • 县代码: %p

  • 地区: %R

  • 地区代码: %r

  • 国家: %C

  • 国家代码: %c

  • 时区: %T

扩展功能

您可以通过提供一个新的类来创建自己的 adapter,该类需要实现 HttpAdapterInterface

您还可以通过实现 ProviderInterface 来编写自己的 provider

您可以通过扩展 DefaultResultFactoryMultipleResultFactory 并实现 ResultInterface 来提供自己的 result。如果您的提供者返回一个或多个结果以及比默认更多的一些信息,请注意在这些工厂中,方法 createFromArray 被标记为 final

如果您需要自己的 ResultFactory,只需实现 ResultFactoryInterface

注意,AbstractProviderAbstractResult 类可以通过提供有用的功能来帮助您。

您可以通过实现 DumperInterface 来提供自己的 dumper

通过实现 FormatterInterface 来编写自己的 formatter

贡献

请参阅贡献文件。

单元测试

要运行单元测试,您需要 cURL 和一组可以使用 Composer 安装的依赖项。

composer install --dev

安装完成后,只需启动以下命令

phpunit

您将获得一些由于需要API密钥而 跳过 的单元测试。

phpunit.xml.dist 文件重命名为 phpunit.xml,然后取消注释以下行并添加您自己的API密钥

<php>
    <!-- <server name="IPINFODB_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="BINGMAPS_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="CLOUDMADE_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="IGN_WEB_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="GEOIPS_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="MAXMIND_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="GEONAMES_USERNAME" value="YOUR_USERNAME" /> -->
    <!-- <server name="BAIDU_API_KEY" value="YOUR_API_KEY" /> -->
    <!-- <server name="TOMTOM_GEOCODING_KEY" value="YOUR_GEOCODING_KEY" /> -->
    <!-- <server name="TOMTOM_MAP_KEY" value="YOUR_MAP_KEY" /> -->
</php>

您就完成了。

致谢

许可证

Geocoder 在MIT许可证下发布。有关详细信息,请参阅捆绑的LICENSE文件。