Geocoder
Geocoder is a library which helps you build geo-aware applications. It provides an abstraction layer for geocoding manipulations.
The library is splitted in two parts: HttpAdapter
and Provider
and is really extensible., (*1)
, (*2)
HttpAdapters
HttpAdapters are responsible to get data from remote APIs., (*3)
Currently, there are the following adapters:, (*4)
-
BuzzHttpAdapter
to use Buzz, a lightweight PHP 5.3 library for issuing HTTP requests;
-
CurlHttpAdapter
to use cURL;
-
GuzzleHttpAdapter
to use Guzzle, PHP 5.3+ HTTP client and framework for building RESTful web service clients;
-
SocketHttpAdapter
to use a socket;
-
ZendHttpAdapter
to use Zend Http Client.
Providers
Providers contain the logic to extract useful information., (*5)
Currently, there are many providers for the following APIs:, (*6)
-
FreeGeoIp as IP-Based geocoding provider;
-
HostIp as IP-Based geocoding provider;
-
IpInfoDB as IP-Based geocoding provider;
-
Yahoo! PlaceFinder as Address-Based geocoding and reverse geocoding provider;
-
Google Maps as Address-Based geocoding and reverse geocoding provider;
-
Google Maps for Business as Address-Based geocoding and reverse geocoding provider;
-
Bing Maps as Address-Based geocoding and reverse geocoding provider;
-
OpenStreetMaps as Address-Based geocoding and reverse geocoding provider;
-
CloudMade as Address-Based geocoding and reverse geocoding provider;
-
Geoip, the PHP extension, as IP-Based geocoding provider;
- ChainProvider is a special provider that takes a list of providers and iterates
over this list to get information;
-
MapQuest as Address-Based geocoding and reverse geocoding provider;
-
OIORest as very accurate Address-Based geocoding and reverse geocoding provider (exclusively in Denmark);
-
GeoCoder.ca as Address-Based geocoding and reverse geocoding provider (exclusively in USA & Canada);
-
GeoCoder.us as Address-Based geocoding provider (exclusively in USA);
-
IGN OpenLS as Address-Based geocoding provider (exclusively in France);
-
DataScienceToolkit as IP-Based geocoding provider;
-
Yandex as Address-Based geocoding and reverse geocoding provider;
-
GeoPlugin as IP-Based geocoding provider;
-
GeoIPs as IP-Based geocoding provider;
-
MaxMind web service as IP-Based geocoding provider.
Installation
The recommended way to install Geocoder is through composer., (*7)
Just create a composer.json
file for your project:, (*8)
``` json
{
"require": {
"willdurand/geocoder": "*"
}
}, (*9)
And run these two commands to install it:
``` bash
$ wget http://getcomposer.org/composer.phar
$ php composer.phar install
Now you can add the autoloader, and you will have access to the library:, (*10)
``` php
<?php, (*11)
require 'vendor/autoload.php';, (*12)
If you don't use neither **Composer** nor a _ClassLoader_ in your application, just require the provided autoloader:
``` php
<?php
require_once 'src/autoload.php';
You're done., (*13)
Usage
First, you need an adapter
to query an API:, (*14)
``` php
<?php, (*15)
$adapter = new \Geocoder\HttpAdapter\BuzzHttpAdapter();, (*16)
The `BuzzHttpAdapter` is tweakable, actually you can pass a `Browser` object to this adapter:
``` php
<?php
$buzz = new \Buzz\Browser(new \Buzz\Client\Curl());
$adapter = new \Geocoder\HttpAdapter\BuzzHttpAdapter($buzz);
Now, you have to choose a provider
which is closed to what you want to get., (*17)
FreeGeoIpProvider
The FreeGeoIpProvider
is able to geocode IPv4 and IPv6 addresses only., (*18)
HostIpProvider
The HostIpProvider
is able to geocode IPv4 addresses only., (*19)
IpInfoDbProvider
The IpInfoDbProvider
is able to geocode IPv4 addresses only.
A valid api key is required., (*20)
YahooProvider
The YahooProvider
is able to geocode both IPv4 addresses and street addresses.
This provider can also reverse information based on coordinates (latitude, longitude).
A valid api key is required., (*21)
GoogleMapsProvider
The GoogleMapsProvider
is able to geocode and reverse geocode street addresses., (*22)
BingMapsProvider
The BingMapsProvider
is able to geocode and reverse geocode street addresses.
A valid api key is required., (*23)
OpenStreetMapsProvider
The OpenStreetMapsProvider
is able to geocode and reverse geocode street addresses., (*24)
CloudMadeProvider
The CloudMadeProvider
is able to geocode and reverse geocode street addresses.
A valid api key is required., (*25)
GeoipProvider
The GeoipProvider
is able to geocode IPv4 and IPv6 addresses only. No need to use an HttpAdapter
as it uses a local database.
See the MaxMind page for more information., (*26)
ChainProvider
The ChainProvider
is a special provider that takes a list of providers and iterates over this list to get information., (*27)
MapQuestProvider
The MapQuestProvider
is able to geocode and reverse geocode street addresses., (*28)
OIORestProvider
The OIORestProvider
is able to geocode and reverse geocode street addresses, exclusively in Denmark., (*29)
GeocoderCaProvider
The GeocoderCaProvider
is able to geocode and reverse geocode street addresses, exclusively in USA & Canada., (*30)
GeocoderUsProvider
The GeocoderUsProvider
is able to geocode street addresses only, exclusively in USA., (*31)
IGNOpenLSProvider
The IGNOpenLSProvider
is able to geocode street addresses only, exclusively in France.
A valid api key is required., (*32)
The DataScienceToolkitProvider
is able to geocode IPv4 addresses only., (*33)
YandexProvider
The YandexProvider
is able to geocode and reverse geocode street addresses.
The default langage-locale is ru-RU
, you can choose between uk-UA
, be-BY
,
en-US
, en-BR
and tr-TR
.
This provider can also reverse information based on coordinates (latitude,
longitude). It's possible to precise the toponym to get more accurate result:
house
, street
, metro
, district
and locality
., (*34)
GeoPluginProvider
The GeoPluginProvider
is able to geocode IPv4 addresses and IPv6 addresses only., (*35)
GeoIPsProvider
The GeoIPsProvider
is able to geocode IPv4 addresses only.
A valid api key is required., (*36)
MaxMindProvider
The MaxMindProvider
is able to geocode IPv4 addresses only.
A valid api key is required., (*37)
You can use one of them or write your own provider. You can also register all providers and decide later.
That's we'll do:, (*38)
``` php
<?php, (*39)
$geocoder = new \Geocoder\Geocoder();
$geocoder->registerProviders(array(
new \Geocoder\Provider\YahooProvider(
$adapter, '', $locale
),
new \Geocoder\Provider\IpInfoDbProvider(
$adapter, ''
),
new \Geocoder\Provider\HostIpProvider($adapter)
));, (*40)
The `$locale` parameter is available for the `YahooProvider`.
Everything is ok, enjoy!
API
---
The main method is called `geocode()` which receives a value to geocode. It can be an IP address or a street address (partial or not).
``` php
<?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) ""
// "city" => string(7) "Orleans"
// "zipcode" => string(0) ""
// "county" => string(6) "Loiret"
// "region" => string(6) "Centre"
// "country" => string(6) "France"
// "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"
// "city" => string(5) "Paris"
// "county" => string(5) "Paris"
// "zipcode" => string(5) "75020"
// "region" => string(14) "Ile-de-France"
// "country" => string(6) "France"
// "timezone" => string(6) "Europe/Paris"
The geocode()
method returns a Geocoded
result object with the following API, this object also implements the ArrayAccess
interface:, (*41)
-
getCoordinates()
will return an array with latitude
and longitude
values;
-
getLatitude()
will return the latitude
value;
-
getLongitude()
will return the longitude
value;
-
getBounds()
will return an array with south
, west
, north
and east
values;
-
getStreetNumber()
will return the street number/house number
value;
-
getStreetName()
will return the street name
value;
-
getCity()
will return the city
;
-
getZipcode()
will return the zipcode
;
-
getCityDistrict()
will return the city district
, or sublocality
;
-
getCounty()
will return the county
;
-
getCountyCode()
will return the county
code (county short name);
-
getRegion()
will return the region
;
-
getRegionCode()
will return the region
code (region short name);
-
getCountry()
will return the country
;
-
getCountryCode()
will return the ISO country
code;
-
getTimezone()
will return the timezone
.
The Geocoder's API is fluent, you can write:, (*42)
``` php
<?php, (*43)
$result = $geocoder
->registerProvider(new \My\Provider\Custom($adapter))
->using('custom')
->geocode('68.145.37.34')
;, (*44)
The `using()` method allows you to choose the `provider` to use. When you deal with multiple providers, you may want to
choose one of them. The default behavior is to use the first one but it can be annoying.
Reverse Geocoding
-----------------
This library provides a `reverse()` method to retrieve information from coordinates:
``` php
$result = $geocoder->reverse($latitude, $longitude);
Dumpers
Geocoder provides dumpers that aim to transform a ResultInterface
object in standard formats., (*45)
The GPS eXchange format is designed to share geolocated data like point of interests, tracks, ways, but also
coordinates. Geocoder provides a dumper to convert a ResultInterface
object in an GPX compliant format., (*46)
Assuming we got a $result
object as seen previously:, (*47)
``` php
<?php, (*48)
$dumper = new \Geocoder\Dumper\GpxDumper();
$strGpx = $dumper->dump($result);, (*49)
echo $strGpx;, (*50)
It will display:
``` xml
<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 is a format for encoding a variety of geographic data structures., (*51)
Keyhole Markup Language (KML)
Keyhole Markup Language is an XML notation
for expressing geographic annotation and visualization within Internet-based, two-dimensional maps
and three-dimensional Earth browsers., (*52)
Well-Known Binary (WKB)
The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specification., (*53)
Well-Known Text (WKT)
Well-known text (WKT) is a text markup language for representing vector geometry objects on a map,
spatial reference systems of spatial objects and transformations between spatial reference systems., (*54)
A common use case is to print geocoded data. Thanks to the Formatter
class,
it's really easy to format a ResultInterface
object as a string:, (*55)
``` php
<?php, (*56)
// $result is an instance of ResultInterface
$formatter = new \Geocoder\Formatter\Formatter($result);, (*57)
$formatter->format('%S %n, %z %L');
// 'Badenerstrasse 120, 8001 Zuerich', (*58)
$formatter->format(', (*59)
%S %n, %z %L, (*60)
');
// ', (*61)
Badenerstrasse 120, 8001 Zuerich, (*62)
', (*63)
Here is the mapping:
* Street Number: `%n`
* Street Name: `%S`
* City: `%L`
* Zipcode: `%z`
* County: `%P`
* County Code: `%p`
* Region: `%R`
* Region Code: `%r`
* Country: `%C`
* Country Code: `%c`
* Timezone: `%T`
Extending Things
----------------
You can provide your own `adapter`, you just need to create a new class which implements `HttpAdapterInterface`.
You can also write your own `provider` by implementing the `ProviderInterface`.
Note, the `AbstractProvider` class can help you by providing useful features.
You can provide your own `dumper` by implementing the `DumperInterface`.
Write your own `formatter` by implementing the `FormatterInterface`.
Unit Tests
----------
To run unit tests, you'll need `cURL` and a set of dependencies you can install using Composer:
php composer.phar install --dev, (*64)
Once installed, just launch the following command:
phpunit, (*65)
You'll obtain some _skipped_ unit tests due to the need of API keys.
Rename the `phpunit.xml.dist` file to `phpunit.xml`, then uncomment the following lines and add your own API keys:
``` xml
<php>
<!-- <server name="IPINFODB_API_KEY" value="YOUR_API_KEY" /> -->
<!-- <server name="YAHOO_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" /> -->
</php>
You're done., (*66)
Credits
License
Geocoder is released under the MIT License. See the bundled LICENSE file for details., (*67)