Installation
composer require lcjury/administrative
Add the provider to config/app.php:
'providers' => [
Lcjury\Administrative\AdministrativeServiceProvider::class,
],
Generate Administrative Structure Run the scaffold command:
php artisan make:administrative
This creates:
Region, Province, Commune)regions, provinces, communes)Seed the Database
Update database/seeders/DatabaseSeeder.php:
public function run()
{
$this->call(PoliticalTablesSeeder::class);
}
Run migrations and seed:
php artisan migrate --seed
Display a Commune Hierarchy
// In a controller or blade view
$regions = \App\Models\Region::with('provinces.communes')->get();
Use this to render dropdowns or nested structures (e.g., for location selectors).
Hierarchical Data Access Define relationships in models (auto-generated by the package):
// Example: Region.php
public function provinces()
{
return $this->hasMany(Province::class);
}
Use eager loading to avoid N+1 queries:
$region = Region::with('provinces.communes')->find(1);
Customizing for Other Countries Override the seeder or extend the package:
PoliticalTablesSeeder to database/seeders/CustomCountrySeeder.call() in DatabaseSeeder.php with your custom seeder.Validation and Forms
Use the models for form validation (e.g., Laravel’s FormRequest):
public function rules()
{
return [
'region_id' => 'required|exists:regions,id',
'province_id' => 'required|exists:provinces,id',
'commune_id' => 'required|exists:communes,id',
];
}
API Responses Serialize hierarchical data for APIs:
return Region::with(['provinces.communes' => function($query) {
$query->select('id', 'name'); // Limit fields
}])->get();
class Commune extends Model
{
use \Laravel\Scout\Searchable;
}
Hardcoded Country Data
Migration Conflicts
regions/provinces tables, the package’s migrations will fail.make:administrative.Relationship Assumptions
Region → Province → Commune hierarchy. Customize if your country uses a different structure (e.g., states/districts).Seeder Overwrites
php artisan db:seed repeatedly will overwrite existing data.--class=CustomSeeder or conditionally insert data in the seeder.php artisan db:seed --class=PoliticalTablesSeeder
province_id in communes table).^0.0.0).Add Custom Fields Extend the migrations or models:
// app/Models/Province.php
protected $fillable = ['name', 'code', 'custom_field'];
Update the seeder to include new fields.
Localization
Store translated names in a localizations table and use Laravel’s localize() or a package like spatie/laravel-translatable.
Geospatial Data
Add latitude/longitude to communes and use spatie/laravel-geotools for distance queries:
class Commune extends Model
{
use \Spatie\Geo\HasGeoCoordinates;
}
Soft Deletes Enable soft deletes in models:
use \Illuminate\Database\Eloquent\SoftDeletes;
protected $dates = ['deleted_at'];
Update migrations to add deleted_at columns.
region_id, province_id in migrations for faster joins.$regions = Cache::remember('regions.hierarchy', now()->addHours(1), function() {
return Region::with('provinces.communes')->get();
});
How can I help you explore Laravel packages today?