Auto-Geocoding
Atlas can automatically geocode new records when they're created, using a queued job.
Enabling the Listener
Set the model and enable the listener in config/atlas.php:
php
'model' => App\Models\Address::class,
'listener' => [
'enabled' => true,
'queue' => 'default', // null for the default queue
'delay' => 2, // seconds before the job runs
'tries' => 3, // retry attempts
],When enabled, Atlas hooks into Model::created on your configured model class and dispatches a GeocodeOnCreated queued job.
How It Works
The GeocodeOnCreated job:
- Freshes the model to get the latest data
- Skips if
latitudeandlongitudeare already set - Skips if the
addresscolumn is empty - Geocodes using the column mapping from config
- Saves with
forceFill()+saveQuietly()(won't trigger other model events) - Dispatches an
AddressGeocodedevent on success - Logs a warning if no result was found
- Retries with exponential backoff on exceptions
The AddressGeocoded Event
After a successful geocode, Atlas dispatches ArielMejiaDev\Atlas\Events\AddressGeocoded:
php
use ArielMejiaDev\Atlas\Events\AddressGeocoded;
class GeocodeListener
{
public function handle(AddressGeocoded $event): void
{
// $event->model — the Eloquent model
// $event->result — the Result value object
Log::info('Geocoded', [
'model' => get_class($event->model),
'id' => $event->model->getKey(),
'method' => $event->result->method,
]);
}
}Alternative: Manual Observer
If you prefer more control, skip the built-in listener and wire your own Observer:
php
// app/Observers/AddressObserver.php
namespace App\Observers;
use App\Models\Address;
use ArielMejiaDev\Atlas\Facades\Atlas;
class AddressObserver
{
public function created(Address $address): void
{
$result = Atlas::geocode([
'address' => $address->street,
'city' => $address->city,
'state' => $address->state,
'zip' => $address->postal_code,
'country' => $address->country,
]);
if ($result) {
$address->forceFill([
'latitude' => $result->latitude,
'longitude' => $result->longitude,
])->saveQuietly();
}
}
}Register it in your AppServiceProvider:
php
use App\Models\Address;
use App\Observers\AddressObserver;
public function boot(): void
{
Address::observe(AddressObserver::class);
}Alternative: Dispatching a Custom Job
For more flexibility (e.g., geocoding on updated too):
php
use ArielMejiaDev\Atlas\Facades\Atlas;
class GeocodeAddress implements ShouldQueue
{
public function __construct(public Address $address) {}
public function handle(): void
{
$address = $this->address->fresh();
if ($address->latitude !== null) {
return;
}
$result = Atlas::geocode([
'address' => $address->street,
'city' => $address->city,
'state' => $address->state,
'zip' => $address->postal_code,
'country' => $address->country,
]);
if ($result) {
$address->forceFill([
'latitude' => $result->latitude,
'longitude' => $result->longitude,
])->saveQuietly();
}
}
}TIP
Always use saveQuietly() when saving from a listener or job to prevent infinite loops.