flairuk / laravel-airports
IATA airport codes for Laravel: an in-memory lookup API, validation rule and optional database table.
Requires
- php: ^8.2
- illuminate/console: ^12.0|^13.0
- illuminate/database: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
- illuminate/validation: ^12.0|^13.0
Requires (Dev)
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0|^11.0
- phpunit/phpunit: ^11.5|^12.0|^13.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-05 11:04:03 UTC
README
Laravel Airports — Over 10,000 IATA airport codes (LHR, JFK, DXB, …) for Laravel 12 and 13.
- No database required. Look airports up through a facade backed by an in-memory dataset.
- Typed results. Every lookup returns readonly
Airportobjects in Laravel collections keyed by code. - Validation rule.
new AirportCodeaccepts known codes only. - Optional table. Publish a migration and seed an
airportstable when other tables need to reference airports.
📦 Installation · 🚀 Usage · 💾 Database table · 🔄 Upgrading
📦 Installation
composer require flairuk/laravel-airports
Requires PHP 8.2 or later with Laravel 12, or PHP 8.3 or later with Laravel 13.
Laravel discovers the service provider and the Airports facade automatically.
🚀 Usage
use FLAIRUK\Airports\Facades\Airports; Airports::find('lhr'); // Airport { id: 4329, code: "LHR", name: "Heathrow", countryCode: "GB" } Airports::findOrFail('LHR'); // throws ItemNotFoundException for unknown codes Airports::exists('JFK'); // true Airports::findById(4329); Airports::all(); // Collection<string, Airport> keyed by code Airports::inCountry('GB'); // airports in the UK Airports::search('heathrow'); // matches on name or exact code Airports::codes(); // ['AAA', 'AAB', ...]
Select options
Airports::options(); // ['LHR' => 'Heathrow', ...] sorted by name Airports::options('id'); // [4329 => 'Heathrow', ...]
Validation
use FLAIRUK\Airports\Rules\AirportCode; $request->validate([ 'origin' => ['required', new AirportCode], 'destination' => ['required', new AirportCode, 'different:origin'], ]);
AirportCode ignores case but different does not, so LHR and lhr would pass as different airports. Uppercase both fields first (for example in a form request's prepareForValidation()) when that matters.
Dependency injection
The facade resolves a singleton FLAIRUK\Airports\Airports, which you can type-hint instead.
💾 Database table (optional)
php artisan airports:install # publish config + migration, then ask to migrate and seed php artisan airports:install --migrate # migrate and seed without asking php artisan airports:seed # insert / update (safe to re-run) php artisan airports:seed --prune # also delete rows no longer in the dataset
You can also call the seeder from your own DatabaseSeeder:
$this->call(\FLAIRUK\Airports\Database\AirportsSeeder::class);
Query the table through the bundled Eloquent model:
use FLAIRUK\Airports\Models\Airport; Airport::code('LHR')->first(); Airport::inCountry('GB')->orderBy('name')->get();
The table name and connection come from AIRPORTS_TABLE and AIRPORTS_DB_CONNECTION, or from the published config.
🔄 Upgrading from dev-master
Version 1.0 is a rewrite. Breaking changes:
| dev-master | 1.0 |
|---|---|
Package ijeffro/laravel-airports |
flairuk/laravel-airports |
ijeffro\Airports\… namespace |
FLAIRUK\Airports\… |
Facade ijeffro\Airports\AirportsFacade |
FLAIRUK\Airports\Facades\Airports (auto-discovered) |
Airports::getList($sort) (array) |
Airports::all()->sortBy($property, SORT_NATURAL | SORT_FLAG_CASE) (Collection of Airport; properties are camelCase, e.g. countryCode) |
Airports::getOne($id) |
Airports::findById($id) or Airports::find($code) |
Airports::getListForSelect() (keyed by id) |
Airports::options('id') |
php artisan airports:migration |
php artisan airports:install / airports:seed |
Config key airports.table_name |
airports.table |
Row ids and columns (code, name, country_code) are unchanged, so existing tables and foreign keys stay valid.
🧪 Testing
composer test
📄 License
MIT. See LICENSE.