PHPackages                             arielmejiadev/atlas - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. arielmejiadev/atlas

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

arielmejiadev/atlas
===================

Offline geocoder for Laravel — fills latitude/longitude from a bundled SQLite database, no API calls.

v2.0.2(1mo ago)158↓66.7%[5 PRs](https://github.com/ArielMejiaDev/atlas/pulls)MITPHPPHP ^8.2CI passing

Since May 27Pushed 1mo agoCompare

[ Source](https://github.com/ArielMejiaDev/atlas)[ Packagist](https://packagist.org/packages/arielmejiadev/atlas)[ Docs](https://github.com/arielmejiadev/atlas)[ GitHub Sponsors](https://github.com/ArielMejiaDev)[ RSS](/packages/arielmejiadev-atlas/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (10)Versions (10)Used By (0)

Atlas — Offline Geocoder for Laravel
====================================

[](#atlas--offline-geocoder-for-laravel)

[![run-tests](https://github.com/arielmejiadev/atlas/actions/workflows/run-tests.yml/badge.svg)](https://github.com/arielmejiadev/atlas/actions/workflows/run-tests.yml)

Fills `latitude` and `longitude` on any Eloquent model from a bundled SQLite database of world cities and US ZIP codes. **No API keys, no rate limits, no network calls at runtime.**

**[Read the full documentation](https://arielmejia.dev/atlas-docs/)**

> **Precision note:** Atlas provides centroid-level precision (city/ZIP center), not street-level geocoding. It's ideal for analytics, clustering, and approximate distance calculations.

Installation
------------

[](#installation)

```
composer require arielmejiadev/atlas
```

Run Migrations
--------------

[](#run-migrations)

```
php artisan migrate
```

This creates the `atlas_coordinates` polymorphic table where coordinates are stored.

Build the Database
------------------

[](#build-the-database)

Atlas ships without the ~22 MB geocoding database. Build it at install time:

```
php artisan atlas:install
```

This downloads ~25 MB of public data from [GeoNames](https://www.geonames.org/) (CC BY 4.0) and builds a local SQLite file. Takes 30–90 seconds.

For air-gapped environments, download a prebuilt file:

```
php artisan atlas:install --from=https://your-host.com/geocoding.sqlite
```

Configuration
-------------

[](#configuration)

Publish the config:

```
php artisan vendor:publish --tag=atlas-config
```

Key options in `config/atlas.php`:

```
return [
    'database_path' => database_path('geocoding.sqlite'),
    'connection_name' => 'atlas',
    'manage_connection' => true,
    'listener' => [
        'enabled' => false,
        'models' => [
            // App\Models\Address::class,
        ],
        'queue' => null,
        'delay' => 2,
        'tries' => 3,
    ],
];
```

Usage
-----

[](#usage)

### Add the Trait

[](#add-the-trait)

```
use ArielMejiaDev\Atlas\Concerns\HasCoordinates;

class Address extends Model
{
    use HasCoordinates;
}
```

### Geocode a Model

[](#geocode-a-model)

```
$address = Address::find(1);
$coordinate = $address->geocode();

$coordinate->latitude;   // 41.4019
$coordinate->longitude;  // -99.6393
$coordinate->method;     // 'us_zip'
```

### Facade

[](#facade)

```
use ArielMejiaDev\Atlas\Facades\Atlas;

$result = Atlas::geocode([
    'address' => '123 Main St',
    'city' => 'Broken Bow',
    'state' => 'NE',
    'zip' => '68815',
    'country' => 'US',
]);
```

### Dependency Injection

[](#dependency-injection)

```
use ArielMejiaDev\Atlas\OfflineGeocoder;

public function store(Request $request, OfflineGeocoder $geocoder)
{
    $result = $geocoder->geocode($request->only('address', 'city', 'state', 'zip', 'country'));
    // ...
}
```

Column Mapping
--------------

[](#column-mapping)

Each model controls its own mapping. Four patterns are supported:

### Standard Columns (Zero Config)

[](#standard-columns-zero-config)

```
class Address extends Model
{
    use HasCoordinates;
    // Works if you have: address, city, state, zip, country columns
}
```

### Custom Column Names

[](#custom-column-names)

```
class Store extends Model
{
    use HasCoordinates;

    public function geocodableColumns(): array
    {
        return [
            'address' => 'store_address',
            'city'    => 'store_city',
            'state'   => 'province',
            'zip'     => 'postal_code',
            'country' => 'country_name',
        ];
    }
}
```

### Partial Data

[](#partial-data)

```
class Venue extends Model
{
    use HasCoordinates;

    public function geocodableColumns(): array
    {
        return [
            'city'    => 'venue_city',
            'country' => 'venue_country',
        ];
    }
}
```

### Single Column / Full Control

[](#single-column--full-control)

```
class Contact extends Model
{
    use HasCoordinates;

    public function toGeocodableArray(): array
    {
        return [
            'address' => $this->full_address ?? '',
            'city'    => '',
            'state'   => '',
            'zip'     => '',
            'country' => '',
        ];
    }
}
```

Backfill Command
----------------

[](#backfill-command)

Geocode existing records in bulk:

```
php artisan atlas:backfill --model=App\\Models\\Address
php artisan atlas:backfill --model=App\\Models\\Store
php artisan atlas:backfill --model=App\\Models\\Address --chunk=1000
php artisan atlas:backfill --model=App\\Models\\Address --force      # re-geocode all
php artisan atlas:backfill --model=App\\Models\\Address --dry-run    # preview without saving
php artisan atlas:backfill --model=App\\Models\\Address --id=42      # single record
```

Auto-Geocode on Create (Listener)
---------------------------------

[](#auto-geocode-on-create-listener)

Opt in via config:

```
// config/atlas.php
'listener' => [
    'enabled' => true,
    'models' => [
        App\Models\Address::class,
        App\Models\Store::class,
    ],
    'queue' => 'default',
    'delay' => 2,
    'tries' => 3,
],
```

New records are automatically geocoded via a queued job.

Geocoding Methods
-----------------

[](#geocoding-methods)

Atlas tries methods in order and returns on the first hit:

\#MethodCondition1`us_zip`US country + valid ZIP code2`us_city_state`US country + city + state3`city_exact`International exact city match4`state_as_city`State field used as city name5`city_partial`Partial/substring city match6`country_centroid`Falls back to country center7`text_extract_city`Detects country from text, finds city8`text_extract_country_centroid`Detected country's center9`global_big_city_match`Last resort: matches big cities globallyRequirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 12 or 13
- Extensions: `pdo_sqlite`, `zip`, `curl`
- Suggested: `intl` (better Unicode transliteration)

Testing
-------

[](#testing)

```
composer test
```

Data Attribution
----------------

[](#data-attribution)

Geocoding data sourced from [GeoNames](https://www.geonames.org/), licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/).

License
-------

[](#license)

MIT. See [LICENSE.md](LICENSE.md).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance92

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 91.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

57d ago

Major Versions

v1.0.0 → v2.0.02026-05-28

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/31971074?v=4)[ArielMejiaDev](/maintainers/ArielMejiaDev)[@ArielMejiaDev](https://github.com/ArielMejiaDev)

---

Top Contributors

[![ArielMejiaDev](https://avatars.githubusercontent.com/u/31971074?v=4)](https://github.com/ArielMejiaDev "ArielMejiaDev (11 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

laravelgeocoderatlasofflinearielmejiadev

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/arielmejiadev-atlas/health.svg)

```
[![Health](https://phpackages.com/badges/arielmejiadev-atlas/health.svg)](https://phpackages.com/packages/arielmejiadev-atlas)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77922.3M186](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[spatie/laravel-export

Create a static site bundle from a Laravel app

674146.0k6](/packages/spatie-laravel-export)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
