Search by

davidamunga / kenya-locations

davidamunga

Kenyan administrative divisions — counties, sub-counties, constituencies, wards, localities, and areas.

Package info

github.com/davidamunga/kenya-locations-php

Homepage

Issues

pkg:composer/davidamunga/kenya-locations

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

0.1.0 2026-09-12 14:34 UTC

This package is auto-updated.

Last update: 2026-09-12 20:25:26 UTC


README

Kenyan administrative divisions — counties, sub-counties, constituencies, wards, localities, and areas — as a typed PHP 8.2+ Composer library.

47 counties · 307 sub-counties · 290 constituencies · 1,448 wards · 916 localities · 1,829 areas

JSON is loaded lazily from the shared data/ files and cached for the process lifetime. No framework or service container is required.

This is the PHP counterpart to the JavaScript, React, Kotlin, Swift, and Dart libraries in the same kenya-locations project, all sourced from the same underlying dataset.

Development happens in the monorepo (packages/php). Packagist is served from the split repo kenya-locations-php.

Installation

composer require davidamunga/kenya-locations

Usage

use KenyaLocations\KenyaLocations;
use KenyaLocations\SearchType;

$counties = KenyaLocations::getCounties();

$nairobi = KenyaLocations::getCountyByName('Nairobi');
echo $nairobi?->capital;          // Nairobi
echo $nairobi?->population2019;   // 4397073
echo $nairobi?->region;           // Nairobi

Drilling down

$constituencies = KenyaLocations::getConstituenciesInCounty('Nairobi');

$wards = KenyaLocations::getWardsInConstituency('Westlands');

$localities = KenyaLocations::getLocalitiesInCounty('Nairobi');

$areas = KenyaLocations::getAreasInLocality('Karen');

Resolving upward

$constituency = KenyaLocations::getConstituencyOfWard('Mountain view');
echo $constituency?->name; // Westlands

// Prefer a ward code when the name is reused (e.g. Township)
$byCode = KenyaLocations::getConstituencyOfWard('1370');

KenyaLocations::getCountyOfWard('1370');
KenyaLocations::getCountyOfConstituency('Westlands');
KenyaLocations::getLocalityOfArea('Gigiri');

// Same locality name in more than one county
$matches = KenyaLocations::getLocalitiesByName('Westlands');
$nairobiOnly = KenyaLocations::getLocality('Westlands', 'Nairobi');

Search

Search is case-insensitive and typo-tolerant, matching common misspellings via Levenshtein distance. It covers counties, sub-counties, constituencies, wards, localities, and areas.

$results = KenyaLocations::search('Nairob', limit: 20);
$wardsOnly = KenyaLocations::searchByType('West', SearchType::Ward);

foreach ($results as $result) {
    echo $result->type->value . ': ' . $result->name() . PHP_EOL;
}

Data model

County (47)
├── code, name, capital, areaKm2, population2019, region, postalCode
├── Locality → Area          (informal addressing: estates, neighbourhoods)
│   916 localities · 1,829 areas
└── Constituency → Ward      (electoral / administrative)
    290 constituencies · 1,448 wards
    └── SubCounty (307)
Type Fields
County code, name, capital, areaKm2, population2019, region, postalCode
SubCounty code, name, county
Constituency code, name, county
Ward code, name, constituency
Locality name, county
Area name, locality, county

API reference

Method Returns
getCounties() list<County>
getCountyByCode(code) ?County
getCountyByName(name) ?County
getSubCounties() list<SubCounty>
getSubCountyByCode(code) ?SubCounty
getSubCountyByName(name) ?SubCounty
getSubCountiesInCounty(nameOrCode) list<SubCounty>
getCountyOfSubCounty(nameOrCode) ?County
getConstituencies() list<Constituency>
getConstituencyByCode(code) ?Constituency
getConstituencyByName(name) ?Constituency
getConstituenciesInCounty(nameOrCode) list<Constituency>
getCountyOfConstituency(nameOrCode) ?County
getConstituencyOfWard(wardNameOrCode) ?Constituency
getWards() list<Ward>
getWardByCode(code) ?Ward
getWardByName(name) ?Ward
getWardsInConstituency(nameOrCode) list<Ward>
getWardsInCounty(nameOrCode) list<Ward>
getWardsInSubCounty(nameOrCode) list<Ward>
getCountyOfWard(wardNameOrCode) ?County
getSubCountyOfWard(wardNameOrCode) ?SubCounty
getLocalities() list<Locality>
getLocalityByName(name) ?Locality
getLocality(name, countyName?) ?Locality
getLocalitiesByName(name) list<Locality>
getLocalitiesInCounty(nameOrCode) list<Locality>
getCountyOfLocality(name) ?County
getAreas() list<Area>
getAreaByName(name) ?Area
getAreasByName(name) list<Area>
getAreasInLocality(localityName) list<Area>
getAreasInCounty(nameOrCode) list<Area>
getCountyOfArea(name) ?County
getLocalityOfArea(name) ?Locality
search(query, limit: 20, types: null) list<SearchResult>
searchByType(query, type, limit: 20) list<SearchResult>

Name lookups are case-insensitive. County, constituency, and sub-county scoped queries accept a name or an administrative code. Ward upward lookups return null when a name is reused (for example Township); use the ward code in that case.

Local development

From this directory:

composer install
composer test

The package ships a copy of the monorepo data/*.json files in data/ so a Packagist install is self-contained. After editing the shared JSON at the repo root, refresh that copy:

composer copy-data

CI fails if the copy is stale. Runtime also falls back to the monorepo data/ directory, so local tests work even before you copy. No codegen step is required.

Contributing

Data corrections and additions belong in the shared data/ JSON files at the root of the kenya-locations monorepo. See the main repo's CONTRIBUTING guide.

License

MIT © David Amunga

Data sourced from the Independent Electoral and Boundaries Commission (IEBC) and Kenya National Bureau of Statistics (KNBS).