pod-point/countries
A Laravel package for working with country data, providing a ready-made list of countries with ISO codes and names, plus helpers for using them in forms, validation, and application logic.
Install the package with Composer and publish any shipped config/seed assets:
composer require pod-point/countries
php artisan vendor:publish --provider="PodPoint\Countries\CountriesServiceProvider"
Check the package README and config/countries.php first — this is where locale behaviour, table names, and lookup sources are configured. If the package ships migrations or a seeder, run them before touching application code:
php artisan migrate
php artisan db:seed --class=CountriesSeeder
The quickest first use case is a country select on a registration or checkout form: pull the country list, render a <select> keyed by ISO alpha-2 code, and validate the submitted value against the package's rule. From v3.2.2 onward you can request Spanish or French country names simply by setting the application locale (es / fr) before resolving the list, so a single set of views can serve multiple storefronts.
Validation. Use the package's country-code rule rather than a hand-rolled in: list. This keeps validation aligned with the data the package ships and automatically covers new territories when you upgrade:
$request->validate([
'country' => ['required', 'string', 'country_code'], // confirm exact rule name in README
]);
Localised name resolution. The headline of v3.2.2 is the addition of es and fr locales. Resolve country names inside the request lifecycle (or explicitly pass a locale) rather than caching a single-language list:
app()->setLocale('fr');
$countries = Countries::all(); // names rendered in French
// or explicit, if the API supports it
Countries::locale('es')->all();
For multi-locale APIs, expose the locale as a request header/query parameter and resolve names per request. Avoid storing localised display names in your own tables unless you also store the locale alongside them.
Form and API presentation. Keep the canonical ISO code as the persisted value and treat the localised name as presentation only:
return CountryResource::collection(
Countries::all()
)->map(fn ($country) => [
'code' => $country->iso_alpha2,
'name' => $country->name,
]);
Caching. Country data is effectively static. Cache the resolved list per locale with a long TTL, and key the cache on the locale so adding es/fr does not cause stale mixed-language payloads:
$countries = Cache::rememberForever("countries.{$locale}", fn () => Countries::locale($locale)->all());
Clear these keys in your deployment script when you bump the package version.
Seeding and testing. In tests, use RefreshDatabase and run the package seeder in setUp rather than asserting against a partially populated table. If you only need a handful of countries in a feature test, seed the full table and query by ISO code — it is faster to reason about than fixture subsets.
de, it, etc. explicitly.'gb' vs 'GB' behaviour depends on the underlying data source and can differ between database collations.php artisan cache:clear (or targeted key deletion) to your release routine.^3.2 in composer.json so you get locale additions without accidentally crossing into a 4.x API rewrite.How can I help you explore Laravel packages today?