Installation:
composer require ijeffro/laravel-cities
For Laravel 5.x, use dev-master as specified in the README.
Register Service Provider & Facade:
Add to config/app.php:
'providers' => [
ijeffro\Cities\CitiesServiceProvider::class,
],
'aliases' => [
'Cities' => ijeffro\Cities\CitiesFacade::class,
],
Publish Migrations (if needed): Run:
php artisan vendor:publish --provider="ijeffro\Cities\CitiesServiceProvider" --tag=migrations
Then migrate:
php artisan migrate
First Use Case: Fetch a city by IATA code:
$city = Cities::findByIata('JFK');
// Returns: ['name' => 'New York', 'country_code' => 'US', ...]
Querying Cities:
$city = Cities::findByIata('LAX'); // Los Angeles
$cities = Cities::findByName('Paris');
$citiesInFrance = Cities::findByCountry('FR');
Integration with Eloquent Models:
Add a relationship to a User model (e.g., for storing preferred cities):
public function preferredCity()
{
return $this->belongsTo(City::class, 'city_id');
}
Use the facade to fetch cities dynamically:
$user->preferredCity = Cities::findByIata($request->iata_code);
Validation: Validate IATA codes in forms:
$validator = Validator::make($request->all(), [
'iata_code' => 'required|exists:cities,iata_code',
]);
API Responses: Return city data in API endpoints:
return response()->json(Cities::findByIata($request->iata));
Custom Queries: Extend the facade or use the underlying repository:
$cities = Cities::repository()->where('country_code', 'US')->get();
Caching: Cache frequent queries (e.g., country dropdowns):
$countries = Cache::remember('countries', 60, function () {
return Cities::getCountries();
});
Localization: Translate city names dynamically:
$city = Cities::findByIata('CDG');
$translatedName = __($city['name']);
Seeding: Use the package to seed cities in a database:
Cities::all()->each(function ($city) {
City::firstOrCreate(['iata_code' => $city['iata_code']], $city);
});
Laravel Version Mismatch:
dev-master branch is Laravel 5.x only. For Laravel 8/9/10, check for updated forks or alternatives like spatie/laravel-cities.Missing Migrations:
cities table won’t exist.php artisan vendor:publish --tag=migrations and migrate.Case Sensitivity:
'JFK' ≠ 'jfk').$city = Cities::findByIata(strtoupper($request->iata));
Data Inconsistencies:
Check Database:
Verify the cities table exists and has data:
php artisan tinker
>>> \DB::table('cities')->count();
Facade vs. Repository:
Cities::repository() for direct query access if the facade doesn’t expose needed methods.Logging: Add debug logs for missing cities:
$city = Cities::findByIata('XYZ');
if (!$city) {
\Log::warning("IATA code 'XYZ' not found in cities database.");
}
Custom Fields:
Add columns to the cities table (e.g., timezone, population) and extend the model:
// In a service provider:
Cities::extend(function ($app) {
$app->bind('city.model', function () {
return new App\Models\ExtendedCity();
});
});
Override Queries: Replace the default repository with a custom implementation:
// In a service provider:
Cities::repository(function () {
return new App\Repositories\CustomCityRepository();
});
Add New Data Sources: Merge with external APIs (e.g., Google Places) by extending the facade:
Cities::extend(function () {
return new App\Services\HybridCityService();
});
Indexing:
Ensure iata_code, name, and country_code are indexed in the cities table for faster lookups.
Batch Fetching:
Use pluck() for lightweight data:
$iataCodes = Cities::pluck('iata_code');
Avoid N+1 Queries: Eager-load relationships when fetching cities for models:
$users = User::with(['preferredCity' => function ($query) {
$query->select('id', 'name', 'iata_code');
}])->get();
How can I help you explore Laravel packages today?