Skip to content

Geocoder Class ​

INFO

This class is very low level. If you want to geocode addresses on save(), look into the Geocoder behavior instead.

Basic usage ​

php
use Geo\Geocoder\Geocoder;

$Geocoder = new Geocoder(['allowInconclusive' => true, 'minAccuracy' => Geocoder::TYPE_POSTAL]);
$addresses = $Geocoder->geocode($address);

if ($addresses->count() > 0) {
    $address = $addresses->first();
}

Since it uses the Google Maps geocoding service by default, make sure to set the corresponding app config:

php
'Geocoder' => [
    'apiKey' => '...',
],

Reverse geocoding ​

php
$result = $Geocoder->reverse($lat, $lng);

Configuration examples below are entries inside the array returned by config/app_local.php. Put any use declarations above that return statement.

Providers ​

The Geocoder supports multiple geocoding providers out of the box. Use provider constants to specify which one to use:

ProviderAPI KeyNotes
Google MapsRequiredDefault
NominatimNo for the public OSM endpointIdentifying User-Agent and service policy required
GeoapifyRequiredConfigure your Geoapify account credentials
NullNoFor testing

The public Nominatim endpoint has a usage policy. Provider support does not grant unlimited requests or permission to use a public service as an automatic overflow backend.

Using string provider names ​

php
use Geo\Geocoder\Geocoder;

// Use Nominatim (OpenStreetMap)
$geocoder = new Geocoder([
    'provider' => Geocoder::PROVIDER_NOMINATIM,
    'nominatim' => ['userAgent' => 'MyApp/1.0 (https://example.com/contact)'],
]);

// Use Geoapify
$geocoder = new Geocoder([
    'provider' => Geocoder::PROVIDER_GEOAPIFY,
    'apiKey' => 'your-geoapify-key',
]);

Provider-specific configuration ​

Configure providers with their specific settings:

php
// config/app_local.php
use Geo\Geocoder\Geocoder;

'Geocoder' => [
    'provider' => Geocoder::PROVIDER_NOMINATIM,
    'allowInconclusive' => true,
    'minAccuracy' => Geocoder::TYPE_COUNTRY,
    'google' => [
        'apiKey' => env('GOOGLE_MAPS_API_KEY'),
        'region' => 'us',
    ],
    'nominatim' => [
        'userAgent' => 'MyApp/1.0', // Required by OSM policy
    ],
    'geoapify' => [
        'apiKey' => env('GEOAPIFY_API_KEY'),
    ],
],

Provider fallback chain ​

Use multiple providers with automatic fallback. If one provider fails due to rate limiting or server errors, the next provider in the chain is tried:

php
use Geo\Geocoder\Geocoder;

'Geocoder' => [
    'providers' => [
        Geocoder::PROVIDER_GOOGLE,    // Try Google first
        Geocoder::PROVIDER_GEOAPIFY,  // Then Geoapify
    ],
    'google' => [
        'apiKey' => env('GOOGLE_MAPS_API_KEY'),
    ],
    'geoapify' => [
        'apiKey' => env('GEOAPIFY_API_KEY'),
    ],
],

The chain automatically handles:

  • QuotaExceeded; API rate limit reached.
  • InvalidServerResponse; server errors or timeouts.

Other exceptions are thrown immediately without trying the next provider. An empty result also ends the chain; fallback handles these exceptions, not missing matches.

Using a callable (advanced) ​

For advanced use cases or custom providers from geocoder-php, use Cake\Http\Client directly (it implements PSR-18):

php
use Cake\Http\Client;

'Geocoder' => [
    'provider' => function () {
        return \Geocoder\Provider\Nominatim\Nominatim::withOpenStreetMapServer(
            new Client(),
            'MyApp/1.0',
        );
    },
],

Creating custom providers ​

You can create custom providers by implementing GeocodingProviderInterface:

php
namespace App\Geocoder\Provider;

use Geo\Geocoder\Provider\AbstractGeocodingProvider;
use Geocoder\Model\AddressCollection;
use Geocoder\Provider\Provider;

class MyCustomProvider extends AbstractGeocodingProvider {

    protected array $_defaultConfig = [
        'apiKey' => null,
        'locale' => 'en',
        'baseUrl' => 'https://api.myservice.com/geocode',
    ];

    public function getName(): string {
        return 'mycustom';
    }

    public function requiresApiKey(): bool {
        return true;
    }

    protected function buildProvider(): Provider {
        // Return a geocoder-php provider instance
        // or throw UnsupportedOperation and override the geocode/reverse methods
    }

}

Register your custom provider:

php
use Geo\Geocoder\Geocoder;
use App\Geocoder\Provider\MyCustomProvider;

// Register the provider
Geocoder::registerProvider('mycustom', MyCustomProvider::class);

// Use it
$geocoder = new Geocoder(['provider' => 'mycustom']);

Or use it directly via a callable:

php
'Geocoder' => [
    'provider' => fn () => new MyCustomProvider(['apiKey' => '...']),
],

See also ​

Released under the MIT License.