Topics covered in this tutorial
- General Background
- Libraries
- Forward geocoding
- Reverse geocoding
- Geocoding a list of places
- Running requests in parallel
- Further reading
Background
Before we dive in to the tutorial
- Sign up for an OpenCage geocoding API key.
- Play with the demo page, so that you see the actual response the API returns.
- Browse the API reference, so you understand the optional parameters, best practices, possible response codes, and the rate limiting on free trial accounts.
PHP libraries for accessing the OpenCage Geocoding API
There are two PHP libraries you can use:
The PHP wrapper attempts to use the CURL extension to access the API. If CURL support is not available, the library falls back to using fopen wrappers.
PHP 8 is supported. For PHP 7.4 you need to use an older version of the library, e.g. version 3.1.0.
To use the wrapper you must either have
the CURL extension compiled into your version of PHP or
configure the use of fopen wrappers via the
allow_url_fopen
directive in your
php.ini
.
The recommended - and easiest way - to install is via Composer. Require the library in your project's composer.json file.
composer require opencage/geocode
Import the Geocoder class.
require "vendor/autoload.php";
Geocode an address (forward geocoding)
$geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY');
# no need to URI encode the query, the library does this for you
$result = $geocoder->geocode('82 Clerkenwell Road, London, UK');
print_r($result);
# set optional parameters
# see the full list: https://opencagedata.com/api#optional-params
#
$result = $geocoder->geocode('6 Rue Massillon, 30020 Nîmes, France', ['language' => 'fr', 'countrycode' => 'fr']);
if ($result && $result['total_results'] > 0) {
$first = $result['results'][0];
print $first['geometry']['lng'] . ';' . $first['geometry']['lat'] . ';' . $first['formatted'] . "\n";
# 4.360081;43.8316276;6 Rue Massillon, 30020 Nîmes, Frankreich
}
Geocode coordinates (reverse geocoding)
$geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY');
$result = $geocoder->geocode('43.831,4.360'); # latitude,longitude (y,x)
print $result['results'][0]['formatted'];
# 3 Rue de Rivarol, 30020 Nîmes, France
Batch geocode addresses
$geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY');
$addresses = ['London', 'Paris, France', 'Berlin'];
$results = [];
foreach ($addresses as $address) {
$result = $geocoder->geocode($address);
$msg = $result['status']['message'];
if ($msg == 'OK'){
$results[$address] = $result;
} else {
error_log("failed to geocode '$addresses' : $msg");
}
}
Set optional parameters
$result = $geocoder->geocode('6 Rue Massillon, 30020 Nîmes, France', [
'language' => 'fr',
'countrycode' => 'fr'
]);
if ($result && $result['total_results'] > 0) {
$first = $result['results'][0];
print $first['geometry']['lng'] . ';' . $first['geometry']['lat'] . ';' . $first['formatted'] . "\n";
// 4.360081;43.8316276;6 Rue Massillon, 30020 Nîmes, Frankreich
}
Set a proxy URL
$geocoder->setProxy('http://proxy.example.com:1234');
$result = $geocoder->geocode("Brandenburger Tor, Berlin");
print_r($result['results'][0]['formatted']);
// Brandenburger Tor, Unter den Linden, 10117 Berlin, Germany
print_r($result['results'][0]['geometry']);
// Array
// (
// [lat] => 52.5166047
// [lng] => 13.3809897
// )
Geocoding faster by running queries in parallel
We created an example how to geocode a file with parallel threads. Before you start geocoding at high volume, please read our guide to geocoding large datasets where we explain various strategies and points to consider.The recommended - and easiest way - to install is via Composer. Require the library in your project's composer.json file.
composer require willdurand/geocoder
Import the Geocoder class.
require "vendor/autoload.php";
use Http\Adapter\Guzzle6\Client as GuzzleAdapter;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
Geocode an address (forward geocoding)
$adapter = new GuzzleAdapter();
$provider = new \Geocoder\Provider\OpenCage\OpenCage($adapter, 'YOUR-API-KEY');
$geocoder = new \Geocoder\StatefulGeocoder($provider, 'en');
$results = $geocoder->geocodeQuery(GeocodeQuery::create('1 Hacker Way, Menlo Park, 94025'));
# print_r($results);
$coords = $results->first()->getCoordinates();
echo json_encode([ 'lat' => $coords->getLatitude(), 'lon' => $coords->getLongitude() ]) . "\n";
Batch geocode addresses
$adapter = new GuzzleAdapter();
$provider = new \Geocoder\Provider\OpenCage\OpenCage($adapter, 'YOUR-API-KEY');
$geocoder = new \Geocoder\StatefulGeocoder($provider, 'en');
$addresses = ['London', 'Paris', 'Berlin'];
$results = [];
foreach ($addresses as $address) {
$result = $geocoder->geocodeQuery(GeocodeQuery::create($address));
$msg = $result['status']['message'];
if ($msg === 'OK') {
$results[$address] = $result;
} else {
error_log("failed to geocode '$addresses' : $msg");
}
}
Geocode coordinates (reverse geocoding)
$adapter = new GuzzleAdapter();
$provider = new \Geocoder\Provider\OpenCage\OpenCage($adapter, 'YOUR-API-KEY');
$geocoder = new \Geocoder\StatefulGeocoder($provider, 'en');
$results = $geocoder->reverseQuery(ReverseQuery::fromCoordinates(37.4856225, -122.1468803));
# print_r($results);
echo $results->first()->getStreetName() . "\n";