Skip to content

Extending Atlas ​

Atlas is designed to be extended. The core geocoder implements the GeocoderDriver interface, making it easy to wrap, decorate, or replace.

The GeocoderDriver Interface ​

php
namespace ArielMejiaDev\Atlas\Contracts;

use ArielMejiaDev\Atlas\Support\Result;

interface GeocoderDriver
{
    public function geocode(array $input): ?Result;
}

Adding an Online Fallback ​

A common pattern is to wrap Atlas with an online geocoder that handles country_centroid or null results:

php
namespace App\Geocoding;

use ArielMejiaDev\Atlas\Contracts\GeocoderDriver;
use ArielMejiaDev\Atlas\Support\Result;

class HybridGeocoder implements GeocoderDriver
{
    public function __construct(
        private GeocoderDriver $offline,
        private OnlineGeocoderService $online,
    ) {}

    public function geocode(array $input): ?Result
    {
        $result = $this->offline->geocode($input);

        // If the offline result is low-confidence, try online
        if ($result === null || in_array($result->method, [
            'country_centroid',
            'text_extract_country_centroid',
            'global_big_city_match',
        ])) {
            $onlineResult = $this->online->geocode($input);

            if ($onlineResult !== null) {
                return $onlineResult;
            }
        }

        return $result;
    }
}

Register it in your service provider:

php
use ArielMejiaDev\Atlas\Contracts\GeocoderDriver;
use ArielMejiaDev\Atlas\OfflineGeocoder;

$this->app->singleton(GeocoderDriver::class, function ($app) {
    return new HybridGeocoder(
        $app->make(OfflineGeocoder::class),
        $app->make(OnlineGeocoderService::class),
    );
});

Custom Normalizer ​

The Normalizer is a regular class that you can extend:

php
namespace App\Geocoding;

use ArielMejiaDev\Atlas\Support\Normalizer;

class CustomNormalizer extends Normalizer
{
    public function normalize(string $s): string
    {
        // Pre-process: expand known abbreviations
        $s = str_replace(['St.', 'Ave.', 'Blvd.'], ['Street', 'Avenue', 'Boulevard'], $s);

        return parent::normalize($s);
    }
}

Bind it in your service provider:

php
$this->app->singleton(Normalizer::class, CustomNormalizer::class);

WARNING

If you customize the normalizer, you must rebuild the database so that the name_norm values in SQLite match your runtime normalization. The builder uses the same Normalizer class.

Listening to Geocode Events ​

Subscribe to AddressGeocoded to run side effects:

php
use ArielMejiaDev\Atlas\Events\AddressGeocoded;

// In EventServiceProvider
protected $listen = [
    AddressGeocoded::class => [
        NotifyGeocodeComplete::class,
        UpdateSearchIndex::class,
    ],
];

Managing the Database Connection ​

By default, Atlas registers its own SQLite connection. If you need custom settings:

php
// config/atlas.php
'manage_connection' => false, // Disable auto-registration
'connection_name' => 'my_geocoder',

Then add the connection yourself in config/database.php:

php
'connections' => [
    'my_geocoder' => [
        'driver' => 'sqlite',
        'database' => database_path('geocoding.sqlite'),
        'prefix' => '',
        'foreign_key_constraints' => false,
    ],
],

Released under the MIT License.