Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Wilayah 2024 Laravel Package

roedyrustam/api-wilayah-2024

Laravel package for Indonesia’s 2024 administrative region data, providing provinces, regencies, districts, and villages with ready-to-use API routes and search for location pickers, address forms, and regional lookups.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and let Laravel's package discovery register the service provider:

composer require roedyrustam/api-wilayah-2024

Publish whatever the package ships (config, migrations, seeders, and—if it exposes HTTP routes—route files). If you're not sure what the provider is named, run php artisan vendor:publish with no arguments and pick the api-wilayah entry from the list; the README will confirm the exact tag.

php artisan vendor:publish --tag=wilayah-config
php artisan vendor:publish --tag=wilayah-migrations   # or the tag shown in the README
php artisan migrate

The dataset is large (roughly 91k rows: 38 provinces, 514 kab/kota, 7,277 kecamatan, 83,763 kelurahan/desa), so seeding is the first thing that will surprise you. Prefer the package's artisan import command if one is provided (e.g. php artisan wilayah:import) over db:seed, and give PHP a generous memory_limit the first time.

Look first at these files after publishing:

  • config/wilayah.php — table names, connection, and any route prefix settings
  • database/migrations/*wilayah* — confirm the schema matches your existing address tables
  • The Models directory — confirm the namespace and relationship names the package uses
  • routes/ — whether it auto-registers JSON endpoints for cascading dropdowns

A quick sanity check:

// php artisan tinker
\RoedyRustam\ApiWilayah\Models\Provinsi::where('kode', '31')->first(); // DKI Jakarta
\RoedyRustam\ApiWilayah\Models\Provinsi::count(); // 38

First use case: an address/checkout form. Drop three or four cascading <select> elements on the page, populate provinces from the package models, then fetch kab/kota, kecamatan, and kelurahan on change via small controller endpoints (or the package's own routes if present). Store the 10-digit BPS kode on your addresses table, not the auto-increment ID — the code is stable across reseeds and is what shipping carriers and Kemendagri-aligned systems expect.

Implementation Patterns

Use kode as the foreign key, everywhere. The package follows the BPS/Kemendagri coding scheme (2 digits province, 4 kab/kota, 6 kecamatan, 10 kelurahan/desa, hierarchical prefixes). Storing kode on your own addresses, users, or orders tables makes the data portable and lets you rebuild the wilayah tables without cascading ID breakage.

Schema::table('addresses', function (Blueprint $t) {
    $t->char(2, 10)->nullable()->index();   // provinsi_kode
    $t->char(4, 10)->nullable()->index();   // kabupaten_kode
    $t->char(6, 10)->nullable()->index();   // kecamatan_kode
    $t->char(10, 10)->nullable()->index();  // kelurahan_kode
});

Cache the lookup layers. Provinces and kab/kota are small and effectively immutable between releases—memoize them forever and bust on redeploy:

$provinces = Cache::rememberForever('wilayah.provinsi', fn () =>
    Provinsi::orderBy('nama')->get(['kode', 'nama'])
);

Do the same for kab/kota keyed by parent, but skip caching the full 83k kelurahan list; query it on demand or cache per-kecamatan.

Cascading endpoints with route-model binding by code. If the package doesn't ship routes, write thin controllers:

Route::get('/wilayah/kabupaten/{provinsi}', fn (string $provinsi) =>
    Kabupaten::where('provinsi_kode', $provinsi)->orderBy('nama')->get(['kode', 'nama'])
);

Then wire Alpine or Livewire to fetch() on change. Keep responses to kode and nama only—serializing full models for 500+ rows per request is wasteful.

Validation. The dataset gives you free exists rules; don't hand-roll arrays:

$request->validate([
    'provinsi_kode'  => ['required', Rule::exists('wilayah_provinsi', 'kode')],
    'kabupaten_kode' => ['required', Rule::exists('wilayah_kabupaten', 'kode')
                          ->where('provinsi_kode', $request->provinsi_kode)],
    // ...
]);

The chained where clauses enforce hierarchy, which catches tampered form posts.

Tests. 90k rows will slow your suite to a crawl if you re-seed on every test. Seed once into a shared test database, or wrap your test class in a transaction and rely on RefreshDatabase's $seed = false. For unit tests of unrelated features, point the package at a SQLite connection you seed in a setUpBeforeClass.

Read-only separation. If the wilayah tables don't belong in your application's primary schema, publish the config and point them at a second connection (a read replica or a dedicated wilayah SQLite file). The package is data-only, so there's no reason to let it bloat your main migration history.

Gotchas and Tips

  • The initial seed is the hard part. Insert in chunks (->chunk(1000) or raw insert() batches of 500–1000), wrap the whole thing in DB::transaction(), and disable foreign key checks (Schema::disableForeignKeyConstraints()) around the load. Without this, 91k Eloquent create() calls will time out.
  • Kode formatting is inconsistent in the wild. Some sources use dotted form (11.01.01.2001), some bare digits. Confirm which the package stores and normalize at your boundary—mix them and your joins silently return nothing.
  • Names are not unique. There are dozens of "Sukamaju" desas and multiple kecamatan sharing a name across provinces. Never look up by nama; always key by kode, and for search UI, show the parent chain in the label ("Sukamaju, Cilodong, Depok").
  • Kabupaten vs Kota and Kelurahan vs Desa are mixed in one table. The nama column typically carries the full official name including the "Kabupaten"/"Kota" prefix. Don't strip prefixes for display without also handling filtering, or users searching "Kota Bandung" miss it.
  • Table name collisions. If you already have provinces/regencies tables from another package, change the package's table names in config/wilayah.php before running the migration, or you'll get duplicate-table errors.
  • Route auto-registration. If the package registers /api/wilayah/* globally, it may collide with your own prefix or leak data outside auth middleware. Disable auto-routes in config and mount them yourself if you need auth/rate limiting.
  • It's a snapshot, not a live feed. "2026 Kemendagri" is a point-in-time dataset; there is no sync job. Plan a yearly refresh: re-run the import into a staging table, diff the codes, and migrate any of your rows whose kode disappeared (pemekaran/mergers do happen). Log orphaned codes rather than letting them fail silently.
  • Cache invalidation after re-import. Any Cache::rememberForever keys you added will survive the reseed. Either version the cache key (wilayah.provinsi.v2026) or flush explicitly in a deploy command.
  • Low-star, single-maintainer package. Pin a specific version ("roedyrustam/api-wilayah-2024": "1.x") rather than floating, read the migration files before trusting them in production, and consider vendoring the seed data (export to CSV/JSON) so a future breaking change or abandonment doesn't strand you. The data itself is the valuable part—your application shouldn't depend heavily on the package's PHP surface.
  • Testing against the API form. If the package exposes HTTP endpoints, tests that mock Http::fake() are fragile because the response shape is the dataset. Prefer hitting the real seeded database in feature tests and reserve HTTP fakes for external services.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings