PHP Geocoding Tutorial

Before we dive in to the tutorial ...

This is a tutorial for using the OpenCage Geocoding API in PHP. Before you can query the API you will need to sign up for an OpenCage API key.

Once you've done that we recommend you spend five minutes on:

Ok, ready?

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.

Works with PHP version 5.6, 7. hhvm version 4 is no longer supported. 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');
$result = $geocoder->geocode('82 Clerkenwell Road, London');
print_r($result);

# set optional parameters
# see the full list: https://opencagedata.com/api#forward-opt
#
$result = $geocoder->geocode('6 Rue Massillon, 30020 Nîmes', ['language' => 'fr', 'countrycode' => 'de']);
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
}

Batch geocode addresses

$geocoder = new \OpenCage\Geocoder\Geocoder('YOUR-API-KEY');

$addresses = ['London', 'Paris', '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");
  }
}

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

Geocoding faster by running queries in parallel

We created an example how to geocode a file with parallel threads.

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";
Start your free trial

2,500 API requests per day.

No credit card required.