willdurand / propel-geocodable-behavior
GeocodableBehavior 帮助您构建地理感知应用程序。在保存模型时自动对其进行地理编码,使您能够通过位置进行搜索并计算记录之间的距离。
Requires
- php: >=5.2.4
- propel/propel1: ~1.6,>=1.6.4
- willdurand/geocoder: ~2.3
README
GeocodableBehavior 帮助您构建地理感知应用程序。在保存模型时自动对其进行地理编码,使您能够通过位置进行搜索并计算记录之间的距离。
此行为使用 Geocoder,Geocoder PHP 5.3 库,并需要 Propel 1.6.4-dev 及以上版本。
安装
选择 GeocodableBehavior.php 文件,并将其放在 src/ 目录中,然后向您的 propel.ini 或 build.properties 配置文件中添加以下行
propel.behavior.geocodable.class = path.to.GeocodableBehavior
用法
只需在您的 schema.xml 文件中添加以下 XML 标签
<behavior name="geocodable" />
基本上,行为将为您的模型添加以下内容
- 两个新列(
latitude和longitude); - 四个新方法到 ActiveRecord API(
getDistanceTo()、isGeocoded()、getCoordinates()和setCoordinates()); - 三个新方法到 ActiveQuery API(
withDistance()、filterByDistanceFrom()和filterNear())。
ActiveRecord API
getDistanceTo() 返回当前对象与给定对象之间的距离。该方法接受两个参数
- 一个地理编码对象;
- 一个测量单位(
KILOMETERS_UNIT、MILES_UNIT或在地理编码模型类的Peer类中定义的NAUTICAL_MILES_UNIT)。
isGeocoded() 返回一个布尔值,表示对象是否已被地理编码。
getCoordinates()、setCoordinates() 允许快速设置/获取纬度和经度值。
ActiveQuery API
withDistance() 接受三个参数
- 一个纬度值;
- 一个经度值;
- 一个测量单位(在地理编码模型类的
Peer类中定义的KILOMETERS_UNIT、MILES_UNIT或NAUTICAL_MILES_UNIT);
它将在当前查询中添加一个 Distance 列,并返回自身以实现流畅的接口。示例用法:结合 orderByDistance() 和 limit() 返回最接近的匹配项。
filterByDistanceFrom() 接受五个参数
- 一个纬度值;
- 一个经度值;
- 一个距离值;
- 一个测量单位(在地理编码模型类的
Peer类中定义的KILOMETERS_UNIT、MILES_UNIT或NAUTICAL_MILES_UNIT); - 一个比较符号(默认值为
Criteria::LESS_THAN)。
它将在当前查询中添加一个基于距离的过滤器,并返回自身以实现流畅的接口。
filterNear 接受三个参数
- 一个模型对象;
- 一个距离值;
- 一个测量单位(
KILOMETERS_UNIT、MILES_UNIT或在地理编码模型类的Peer类中定义的NAUTICAL_MILES_UNIT)。
自动地理编码
在这个步骤中,您必须自行填写两个列(latitude 和 longitude)。这难道不是很实用吗?
自动地理编码来拯救!有两种自动方式来获取地理编码信息
- 使用 IP 地址;
- 使用街道地址。
它提供了一个 geocode() 方法,可以自动更新位置值。为防止修改时自动填充,只需将 auto_update 属性设置为 false。
此方法返回一个 ResultInterface 对象,因此您可以重写此方法,根据您的模型填充更多字段
<?php class MyObject extends BaseMyObject { // ... /** * {@inheritdoc} */ public function geocode() { if (null !== $result = parent::geocode()) { if ($city = $result->getCity()) { $this->setCity($city); } } return $result; } }
注意:您可以使用这两个方法同时使用。
基于 IP 的地理编码
要启用基于 IP 的地理编码,请将以下配置添加到您的 schema.xml 文件中
<behavior name="geocodable"> <parameter name="geocode_ip" value="true" /> <parameter name="geocoder_api_key" value="<API_KEY>" /> <parameter name="geocoder_api_key_provider" value="<API_KEY_PROVIDER>" /> </behavior>
geocoder_api_key_provider 可以是返回 API 密钥的静态方法。格式为 class()->method() 或 class()->method()->subMethod() 的类方法,或者实现 getGoogleMapsKey 的类,该类必须返回密钥。
默认情况下,默认的 Geocoder provider 是 YahooProvider,因此您需要填写一个 API 密钥。
如果您想使用其他提供商,您需要设置新的参数
<parameter name="geocoder_provider" value="\Geocoder\Provider\HostIpProvider" />
阅读 Geocoder 文档以了解更多有关提供商的信息。
此配置将在您的模型中添加一个新列:ip_address。您可以使用以下参数更改此列的名称
<parameter name="ip_column" value="ip" />
现在,行为将使用 ip_address 值通过 Geocoder 来填充 latitude 和 longitude 列
基于地址的地理编码
要启用基于地址的地理编码,请添加以下配置
<behavior name="geocodable"> <parameter name="geocode_address" value="true" /> <parameter name="geocoder_api_key" value="<API_KEY>" /> </behavior>
默认情况下,默认的 Geocoder provider 是 YahooProvider,因此您需要填写一个 API 密钥,但请注意,这取决于您选择的提供商,是一个可选参数。
如果您想使用其他提供商,您需要设置新的参数
<parameter name="geocoder_provider" value="\Geocoder\Provider\GoogleMapsProvider" />
阅读 Geocoder 文档以了解更多有关提供商的信息。
基本上,行为会查找名为 street、locality、region、fpostal_code 和 country 的属性。它试图使用这些属性创建一个完整的地址。像往常一样,您可以调整此参数以添加代表完整街道地址的自己的属性列表
<parameter name="address_columns" value="street,locality,region,postal_code,country" />
这些参数将连接起来,并用逗号分隔,以形成一个街道地址。此地址将用于获取 latitude 和 longitude 值。
现在,每次您保存对象时,latitude 和 longitude 这两列都会通过 Geocoder 填充。
HTTP 适配器
Geocoder 提供了可以通过行为配置的 HTTP 适配器。默认情况下,此行为使用 CurlHttpAdapter。
如果您想使用其他 adapter,您需要使用以下参数
<parameter name="geocoder_adapter" value="\Geocoder\HttpAdapter\BuzzHttpAdapter" />
阅读 Geocoder 文档以了解更多有关适配器的信息。
参数
<behavior name="geocodable"> <parameter name="auto_update" value="true" /> <parameter name="latitude_column" value="latitude" /> <parameter name="longitude_column" value="longitude" /> <parameter name="type" value="DOUBLE" /> <parameter name="size" value="10" /> <parameter name="scale" value="8" /> <!-- IP-Based Geocoding --> <parameter name="geocode_ip" value="false" /> <parameter name="ip_column" value="ip_address" /> <!-- Address-Based Geocoding --> <parameter name="geocode_address" value="false" /> <parameter name="address_columns" value="street,locality,region,postal_code,country" /> <!-- Geocoder --> <parameter name="geocoder_provider" value="\Geocoder\Provider\YahooProvider" /> <parameter name="geocoder_adapter" value="\Geocoder\HttpAdapter\CurlHttpAdapter" /> <parameter name="geocoder_api_key" value="false" /> <parameter name="geocoder_api_key_provider" value="false" /> </behavior>
这是默认配置。
致谢
William Durand william.durand1@gmail.com