eka/world
Laravel package providing a comprehensive world database: countries, states, cities, timezones, currencies, and languages. Query via a World facade or ready-made API routes, with filtering and eager-loaded related data (e.g., states/cities by country).
Installation
composer require eka/world
php artisan vendor:publish --tag=world
php artisan migrate
php artisan db:seed --class=WorldSeeder # (~15 min runtime)
world database tables (countries, states, cities, etc.) exist in your migrations folder.First Query (Facade)
use eka\World\World;
$countries = World::countries()->data;
$countries for an array of country objects with id, name, and code.First Query (API Route)
/api/countries (or your configured route) to see a JSON response of all countries./api/countries?search=usa or /api/states?filters[country_code]=US.eka\World\World class (documented in src/World.php).routes/web.php (check config/world.php for customization).database/migrations/ for table structures (e.g., states has country_code as a foreign key).database/seeders/WorldSeeder.php (for debugging seeding issues).// In a Blade template or controller
$countries = World::countries()->data;
return view('locations.select-country', compact('countries'));
<select name="country">
@foreach($countries as $country)
<option value="{{ $country->code }}">{{ $country->name }}</option>
@endforeach
</select>
Facade Methods:
// Get all countries with eager-loaded states
$countries = World::countries()->with('states')->data;
// Get a single country by code
$country = World::country('US')->data;
// Get states for a country (with cities)
$states = World::states(['country_code' => 'US'])->with('cities')->data;
->with() to eager-load relationships (e.g., states, cities, timezones).API Endpoints:
/api/countries (GET): List all countries./api/countries/{code} (GET): Single country./api/states?filters[country_code]=US (GET): Filter states by country.?fields=id,name,code).// Search countries by name
$results = World::countries(['search' => 'rom'])->data;
// Filter states by country code and region code
$states = World::states([
'country_code' => 'US',
'region_code' => 'CA' // e.g., California
])->data;
/api/cities?filters[country_code]=US&filters[state_code]=CA
// Get countries with their states and cities
$countries = World::countries()->with(['states.cities'])->data;
states (for countries)cities (for states)timezones, currencies, languages (for countries).Selective Fields:
$countries = World::countries(['fields' => 'id,name,code'])->data;
/api/countries?fields=id,name,code.Pagination (API only):
/api/countries?page=2&per_page=10
Use the package to validate country/state/city codes:
use eka\World\Rules\ValidCountryCode;
$request->validate([
'country_code' => ['required', new ValidCountryCode],
'state_code' => ['required_if:country_code,US', 'string', 'max:5'],
]);
Cache frequent queries (e.g., country lists) in AppServiceProvider:
public function boot()
{
Cache::remember('world.countries', now()->addHours(1), function () {
return World::countries()->data;
});
}
Override country/state names for localization:
// In a language file (e.g., resources/lang/en/countries.php)
return [
'US' => 'United States of America',
'GB' => 'United Kingdom',
];
eka\World\World facade to merge these translations.Mock the facade in tests:
$mockCountries = collect([new Country(['code' => 'US', 'name' => 'USA'])]);
World::shouldReceive('countries')->andReturn((object) ['success' => true, 'data' => $mockCountries]);
Add custom fields to existing tables via migrations:
Schema::table('countries', function (Blueprint $table) {
$table->string('iso3')->nullable()->after('code');
});
WorldSeeder) to populate new fields.Seeder Runtime:
WorldSeeder takes ~15 minutes to run. Seed in a staging environment first.--force to skip existing data:
php artisan db:seed --class=WorldSeeder --force
State Code Length:
state_code length limit of 3 characters. v1.1.28+ supports up to 5.Schema::table('states', function (Blueprint $table) {
$table->string('code')->change();
});
API Route Conflicts:
/api/countries, /api/states) may conflict with existing routes.config/world.php:
'api_prefix' => 'geo',
Case Sensitivity:
US ≠ us).$countryCode = strtoupper($request->input('country_code'));
Missing Relationships:
null:
$country = World::country('BV')->data; // Bouvet Island (no cities)
if (!$country->states->isEmpty()) { ... }
Seeder Errors:
storage/logs/laravel.log for seeder failures.WorldSeeder.php.API Response Issues:
success flag:
if (!World::countries()->success) {
Log::error('World API error:', ['data' => World::countries()->data]);
}
Database Mismatches:
database/migrations/ with the package’s default schema (in src/database/migrations/).php artisan migrate:rollback
php artisan migrate
Performance:
Schema::table('states', function (Blueprint $table) {
$table->foreign('country_code')->references('code')->on('countries')->onDelete('cascade');
});
Extending the Package:
Country, State, or City models (published in app/Models/ after publishing).flag_url to countries:
// app/Models/Country.php
protected $appends = ['flag_url'];
public function getFlagUrlAttribute() {
return "https://flagcdn.com/w80/{$this->code}.png";
}
Testing Locally:
https://laravel-world.com/api/countries) as a fallback if seeding fails.Configuration:
How can I help you explore Laravel packages today?