pirumart / uganda-administrative-units
Laravel Package for administrative units of Uganda (Regions, Districts, Counties, Sub-Counties, Parish and Villages)
Package info
github.com/pirumart/uganda-administrative-units
pkg:composer/pirumart/uganda-administrative-units
Requires
- php: ^8.2
- illuminate/contracts: ^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- orchestra/testbench: ^10.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
This package is auto-updated.
Last update: 2026-07-23 10:31:02 UTC
README
A Laravel package providing Eloquent models and migrations for Uganda's administrative units hierarchy: Region → District → County → Sub-County → Parish → Village.
Requires PHP ^8.2 and Laravel 12.
Installation
You can install the package via composer:
composer require pirumart/uganda-administrative-units
Publish and run the migration with:
php artisan vendor:publish --provider="Pirumart\Uganda\Locale\AdministrativeUnitsServiceProvider" --tag="administrative-units-migrations" php artisan migrate
This creates the regions, districts, counties, sub_counties, parishes and
villages tables. All of them use natural business keys (e.g. district_code,
county_code) rather than surrogate foreign keys.
Usage
Each model exposes relations to its parent and child units in the hierarchy:
use Pirumart\Uganda\Locale\Models\District; $district = District::where('district_code', 'D01')->first(); $district->region()->first(); // parent Region $district->counties; // child Counties $district->sub_counties; // child SubCounties $district->parishes; // child Parishes $district->villages; // child Villages
use Pirumart\Uganda\Locale\Models\Village; $village = Village::where('village_code', 'V01')->first(); $village->district; // parent District $village->county; // parent County $village->sub_county; // parent SubCounty $village->parish; // parent Parish
Known limitation: District::region()
District has both a region column (the region name, stored as a string) and a
region() relation method of the same name. Eloquent's attribute accessor always
takes priority over a relation of the same name for magic property access, so
$district->region returns the string column - not the related Region model.
Call the relation explicitly instead:
$district->region()->first();
Seed data
database/seeds/ contains a seeder per table (RegionTableSeeder,
DistrictTableSeeder, etc.), backed by the real Uganda administrative data in
database/data/*.csv (17 regions, 146 districts, 321 counties, 2105
sub-counties, 10322 parishes, 36839 villages). UgandaLocaleSeeder runs all six
in hierarchy order.
District/region counts reflect Uganda's current administrative boundaries, including the 2020 municipal-to-city reform (10 new cities) and 12 districts created since. County/sub-county/parish/village data has now been reconciled for 21 of those 22 districts; Madi Okollo has counties/sub-counties but no parish/village data yet - see CHANGELOG.
The easiest way to populate the tables is the console command:
php artisan uganda-administrative-units:seed
Or run UgandaLocaleSeeder directly - it's autoloaded under
Pirumart\Uganda\Locale\Database\Seeders:
use Pirumart\Uganda\Locale\Database\Seeders\UgandaLocaleSeeder; (new UgandaLocaleSeeder())->run();
Factories
Each model has a factory for use in tests, generating fake codes/names instead of depending on the full CSV datasets:
use Pirumart\Uganda\Locale\Models\Village; Village::factory()->create(); // a single fake village, no seeding required
Testing
composer test
Static analysis (PHPStan/Larastan) and code style (Laravel Pint) are also available:
composer analyse composer format
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details. If you're a coding agent working on this repository, also read AGENTS.md.
License
The MIT License (MIT). Please see License File for more information.