kossa/algerian-cities
Laravel package that ships Algeria's administrative divisions, wilayas (provinces) and communes, as ready-made Eloquent models, migrations and seeders. Add reliable Algerian location data to your app fast, complete with relationships and easy lookup helpers.
The v4.1.2 release is a compatibility/maintenance update rather than a feature release — its headline change is Laravel 12 support, alongside PHP 8.4 CI coverage and Larastan 3.0 for static analysis. Practically: if you were blocked from upgrading to Laravel 12 because of this package's version constraint, bump kossa/algerian-cities to ^4.1.2 in composer.json and run composer update kossa/algerian-cities.
Minimal setup for a fresh install:
composer require kossa/algerian-citiesphp artisan vendor:publish --tag="algerian-cities" — check config/algerian-cities.php after publishing.<select> for wilaya → commune in a registration or shipping address form. Wilaya::all() for the top-level dropdown, then Commune::where('wilaya_id', $id) for the dependent one.Look first at:
id/code/name/wilaya_id vs daira_id) — the schema is what most integration bugs hinge on.Form selects with validation. Load wilayas via a cached repository, validate the pair server-side with a scoped exists rule:
$request->validate([
'wilaya_id' => ['required', 'exists:wilayas,id'],
'commune_id' => [
'required',
Rule::exists('communes', 'id')->where('wilaya_id', $request->wilaya_id),
],
]);
The nested where is essential — a plain exists lets a user submit a valid commune that doesn't belong to the chosen wilaya, which is the classic address-corruption bug with this kind of data.
Cache aggressively. The dataset is static. Wrap lookups:
$wilayas = Cache::rememberForever('wilayas.all', fn () => Wilaya::orderBy('name')->get());
$communes = Cache::rememberForever("communes.{$wilayaId}", fn () => Commune::where('wilaya_id', $wilayaId)->orderBy('name')->get());
Flush these keys in your deploy script or in a custom seeder command since the dataset effectively never changes between deploys.
Extend the models rather than referencing the vendor namespace. Subclass or alias:
namespace App\Models;
use Kossa\AlgerianCities\Models\Wilaya as BaseWilaya;
class Wilaya extends BaseWilaya
{
public function addresses() { return $this->hasMany(Address::class); }
}
Then override the model class in the published config so package internals (API controllers, relations) use your subclass.
API consumption. If the package exposes routes, keep them behind a rate-limited group and version the endpoint in your own route file (/api/v1/wilayas) so a vendor route rename doesn't break consumers. If your frontend is a livewire/vue app, serialize the wilaya→commune structure once at boot as a single JSON payload rather than N requests.
Migration strategy in tests. Re-seeding the full dataset per test case is prohibitively slow. In TestCase, either seed once via a trait and use transactions, or use a tiny fixture set of 2–3 wilayas — the package's relationship logic doesn't care about dataset size.
composer.json that Laravel 12 is actually in the illuminate/* constraint before planning an upgrade; if your app is on Laravel 11 or older, there is nothing in this release you need.larastan ^3.0 in your own app, be aware the package now assumes Larastan 3.x — mixing Larastan 2.x in a monorepo can produce conflicting dependency resolutions.whereHas('daira').composer.lock and diff the seed data between upgrades if you expose wilaya lists to end users; an ID shift can silently re-map stored addresses.vendor:publish tag collisions. If you've published the migrations, later package migration updates won't apply automatically. Keep a note in your upgrade runbook to re-publish on minor version bumps.disableForeignKeyConstraints(); a naive per-row migration can take minutes on shared hosting.RefreshDatabase will drop the seeded tables between tests. Use DatabaseTransactions for tests that need the dataset, and a separate trait for fixture-seeded schema tests.code over editing the vendor migrations — that survives upgrades cleanly.Upgrade checklist for this release: bump to ^4.1.2, run composer update, run your static analyser (Larastan 3 expects stricter typing — watch for new errors in code that touches these models), and smoke-test the form flows and any cached lookup keys.
How can I help you explore Laravel packages today?