| Install | |
|---|---|
composer require aliziodev/laravel-indonesia-regions |
|
| Latest Version: | v1.0.13 |
| PHP: | ^8.2|^8.3 |
Package Laravel untuk data wilayah Indonesia lengkap dengan kode pos. Package ini menyediakan data provinsi, kota/kabupaten, kecamatan, dan desa/kelurahan.
Package ini dipertahankan sebagai package kompatibilitas untuk integrasi lama. Dataset package ini disinkronkan dari repo upstream aliziodev/laravel-wilayah dan disimpan sebagai file PHP agar install dan update tetap lintas database.
Indonesia atau IDcomposer updatecomposer require aliziodev/laravel-indonesia-regions
Kemudian jalankan command instalasi:
php artisan indonesia-regions:install
Untuk menyinkronkan dataset terbaru setelah package diupdate:
php artisan indonesia-regions:sync
Opsional, publish konfigurasi cache package:
php artisan vendor:publish --tag=indonesia-regions-config
Data package ini digenerate dari repo upstream berikut:
https://github.com/aliziodev/laravel-wilayah
Saat workflow sync berjalan, package akan mengambil dataset dari repo upstream tersebut, menyalinnya ke folder data/, lalu aplikasi pengguna cukup menjalankan php artisan indonesia-regions:sync untuk melakukan upsert ke database.
Package ini menyediakan endpoint API bawaan tanpa perlu membuat controller sendiri. Secara default route akan aktif dengan prefix:
/api/indonesia-regions
Konfigurasi tersedia di config/indonesia-regions.php:
'api' => [
'enabled' => true,
'prefix' => 'api/indonesia-regions',
'middleware' => ['api'],
'responder' => null,
],
Jika aplikasi Anda memiliki wrapper response sendiri, Anda bisa mengganti responder bawaan package:
'api' => [
'enabled' => true,
'prefix' => 'api/indonesia-regions',
'middleware' => ['api'],
'responder' => App\Support\Api\RegionApiResponder::class,
],
Class tersebut harus mengimplementasikan Aliziodev\IndonesiaRegions\Contracts\ApiResponderInterface.
Contoh implementasi:
<?php
namespace App\Support\Api;
use Aliziodev\IndonesiaRegions\Contracts\ApiResponderInterface;
use Illuminate\Http\JsonResponse;
class RegionApiResponder implements ApiResponderInterface
{
public function respond(mixed $data, int $status = 200): JsonResponse
{
return response()->json([
'success' => true,
'data' => $data,
], $status);
}
}
Contoh jika aplikasi Anda sudah punya helper seperti ApiResponse:
<?php
namespace App\Support\Api;
use Aliziodev\IndonesiaRegions\Contracts\ApiResponderInterface;
use Illuminate\Http\JsonResponse;
class RegionApiResponder implements ApiResponderInterface
{
public function respond(mixed $data, int $status = 200): JsonResponse
{
return ApiResponse::success($data, status: $status);
}
}
Endpoint yang tersedia:
GET /api/indonesia-regionsGET /api/indonesia-regions/cascadeGET /api/indonesia-regions/selectGET /api/indonesia-regions/search?term=bakonganGET /api/indonesia-regions/search/address?term=bakonganGET /api/indonesia-regions/search/full-text?term=acehGET /api/indonesia-regions/postal-code/23773GET /api/indonesia-regions/11.01.01.2001GET /api/indonesia-regions/11.01.01.2001/infoGET /api/indonesia-regions/11.01.01.2001/select-contextGET /api/indonesia-regions/11.01.01.2001/full-address?country_name=IDContoh endpoint options untuk frontend:
GET /api/indonesia-regions/select
GET /api/indonesia-regions/select?parent_code=11
GET /api/indonesia-regions/select?format=map
Response default:
[
{ "value": "11", "label": "ACEH" }
]
Response format=map:
{
"11": "ACEH"
}
Untuk frontend yang ingin langsung mendapat semua options bertingkat sekaligus, gunakan endpoint cascade:
GET /api/indonesia-regions/cascade
GET /api/indonesia-regions/cascade?region_code=11.01.01.2001
GET /api/indonesia-regions/cascade?region_code=11.01.01.2001&country_name=ID
Response:
{
"selected": {
"province": { "value": "11", "label": "Aceh" },
"city": { "value": "11.01", "label": "Kab. Aceh Selatan" },
"district": { "value": "11.01.01", "label": "Bakongan" },
"village": { "value": "11.01.01.2001", "label": "Keude Bakongan", "postal_code": "23773" }
},
"options": {
"provinces": [
{ "value": "11", "label": "ACEH" }
],
"cities": [
{ "value": "11.01", "label": "KAB. ACEH SELATAN" }
],
"districts": [
{ "value": "11.01.01", "label": "BAKONGAN" }
],
"villages": [
{ "value": "11.01.01.2001", "label": "KEUDE BAKONGAN" }
]
},
"full_address": "Keude Bakongan, Bakongan, Kab. Aceh Selatan, Aceh, ID, 23773"
}
Contoh helper untuk prefill cascading select dari region_code yang sudah tersimpan:
GET /api/indonesia-regions/11.01.01.2001/select-context
GET /api/indonesia-regions/11.01.01.2001/select-context?country_name=ID
Response:
{
"selected": {
"province": { "value": "11", "label": "Aceh" },
"city": { "value": "11.01", "label": "Kab. Aceh Selatan" },
"district": { "value": "11.01.01", "label": "Bakongan" },
"village": { "value": "11.01.01.2001", "label": "Keude Bakongan", "postal_code": "23773" }
},
"full_address": "Keude Bakongan, Bakongan, Kab. Aceh Selatan, Aceh, Indonesia, 23773"
}
Contoh kode wilayah yang digunakan:
32 : Jawa Barat32.73 : Kota Bandung32.73.02 : Coblong32.73.02.1001 : DagoAmbil daftar kota/kabupaten di Jawa Barat:
GET /api/indonesia-regions?parent_code=32
Ambil options kota/kabupaten untuk dropdown:
GET /api/indonesia-regions/select?parent_code=32
Atau ambil seluruh context cascade sekaligus:
GET /api/indonesia-regions/cascade?region_code=32.73.02.1001
Response:
[
{ "value": "32.73", "label": "KOTA BANDUNG" },
{ "value": "32.04", "label": "KAB. BANDUNG" }
]
Cari wilayah dengan kata kunci Bandung:
GET /api/indonesia-regions/search?term=bandung
Cari hanya level kota/kabupaten:
GET /api/indonesia-regions/search?term=bandung&type=city
Cari full text, hasil selalu village:
GET /api/indonesia-regions/search/full-text?term=bandung
GET /api/indonesia-regions/search/full-text?term=coblong
GET /api/indonesia-regions/search/full-text?term=dago&country_name=ID
Contoh response:
[
{
"code": "32.73.02.1001",
"province": "Jawa Barat",
"city": "Kota Bandung",
"district": "Coblong",
"village": "Dago",
"postal_code": "40135",
"full_address": "Dago, Coblong, Kota Bandung, Jawa Barat, ID, 40135"
}
]
Ambil detail region berdasarkan kode:
GET /api/indonesia-regions/32.73
GET /api/indonesia-regions/32.73.02.1001
Ambil hierarchy lengkap berdasarkan region_code:
GET /api/indonesia-regions/32.73.02.1001/info
GET /api/indonesia-regions/32.73.02.1001/info?country_name=ID
Contoh response:
{
"province": {
"code": "32",
"name": "Jawa Barat"
},
"city": {
"code": "32.73",
"name": "Kota Bandung"
},
"district": {
"code": "32.73.02",
"name": "Coblong"
},
"village": {
"code": "32.73.02.1001",
"name": "Dago",
"postal_code": "40135"
},
"full_address": "Dago, Coblong, Kota Bandung, Jawa Barat, Indonesia, 40135"
}
Ambil alamat lengkap saja:
GET /api/indonesia-regions/32.73.02.1001/full-address
GET /api/indonesia-regions/32.73.02.1001/full-address?country_name=ID
Response:
{
"full_address": "Dago, Coblong, Kota Bandung, Jawa Barat, ID, 40135"
}
Ambil region dari kode pos:
GET /api/indonesia-regions/postal-code/40135
Prefill cascading select dari region_code yang sudah tersimpan:
GET /api/indonesia-regions/32.73.02.1001/select-context
Response:
{
"selected": {
"province": { "value": "32", "label": "Jawa Barat" },
"city": { "value": "32.73", "label": "Kota Bandung" },
"district": { "value": "32.73.02", "label": "Coblong" },
"village": { "value": "32.73.02.1001", "label": "Dago", "postal_code": "40135" }
},
"full_address": "Dago, Coblong, Kota Bandung, Jawa Barat, Indonesia, 40135"
}
Package ini mendukung dua gaya penulisan parameter:
// Parameter harus sesuai urutan
$cities = Indonesia::getRegions('11', ['code', 'name'], 15);
// Urutan tidak penting, lebih jelas dan mudah dibaca
$cities = Indonesia::getRegions(
parentCode: '11',
columns: ['code', 'name'],
perPage: 15
);
Kedua gaya penulisan akan memberikan hasil yang sama. Named parameters (PHP 8.0+) memiliki beberapa keunggulan:
use Aliziodev\IndonesiaRegions\Facades\Indonesia;
// Mengambil semua provinsi
$provinces = Indonesia::getRegions();
// Response:
[
{
"code": "11",
"name": "ACEH",
},
{
"code": "12",
"name": "SUMATERA UTARA",
}
]
// Mengambil kota/kabupaten di Aceh dengan pagination
$cities = Indonesia::getRegions('11', ['code', 'name'], 15);
// Response dengan pagination:
{
"current_page": 1,
"data": [
{
"code": "11.01",
"name": "KAB. ACEH SELATAN",
},
// ... more cities
],
"first_page_url": "http://example.com/api?page=1",
"from": 1,
"last_page": 23,
"last_page_url": "http://example.com/api?page=23",
"next_page_url": "http://example.com/api?page=2",
"path": "http://example.com/api",
"per_page": 15,
"prev_page_url": null,
"to": 15,
"total": 343
}
// postal_code hanya muncul untuk desa/kelurahan
Perlu diingat bahwa jika parameter columns tidak diisi (null), maka akan menggunakan default columns yaitu ['code', 'name', 'postal_code']. Untuk mengambil semua kolom, Anda perlu secara eksplisit menentukan columns: ['*'].
use Aliziodev\IndonesiaRegions\Facades\Indonesia;
// Pencarian umum
$results = Indonesia::search('Bakongan');
// Search bersifat case-insensitive, termasuk di PostgreSQL
$results = Indonesia::search('bakongan');
$results = Indonesia::search('BAKONGAN');
// Response:
[
{
"code": "11.01.01",
"name": "BAKONGAN"
},
{
"code": "11.01.01.2001",
"name": "KEUDE BAKONGAN",
"postal_code": "23773" // postal_code hanya muncul untuk desa/kelurahan
}
]
// Pencarian dengan tipe spesifik
$villages = Indonesia::search('Bakongan', 'village');
// Pencarian dengan kolom tambahan
$results = Indonesia::search('Bakongan', null, null, ['code', 'name']);
// Pencarian lengkap dengan named parameters (PHP 8.0+)
$results = Indonesia::search(
term: 'Bakongan',
type: 'village',
perPage: 15,
columns: ['code', 'name']
);
// Response dengan pagination sama dengan format getRegions()
use Aliziodev\IndonesiaRegions\Facades\Indonesia;
// Pencarian umum dengan alamat lengkap
$results = Indonesia::searchWithAddress('Bakongan');
// Response:
[
{
"code": "11.01.01",
"name": "BAKONGAN",
"full_address": "BAKONGAN, KAB. ACEH SELATAN, ACEH"
},
{
"code": "11.01.01.2001",
"name": "KEUDE BAKONGAN",
"postal_code": "23773",
"full_address": "KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, 23773"
}
]
// Pencarian dengan tipe spesifik
$villages = Indonesia::searchWithAddress('Bakongan', 'village');
// Pencarian dengan kolom tambahan
$results = Indonesia::searchWithAddress('Bakongan', null, null, ['code', 'name']);
// Pencarian lengkap dengan named parameters (PHP 8.0+)
$results = Indonesia::searchWithAddress(
term: 'Bakongan',
type: 'village',
perPage: 15,
columns: ['code', 'name']
);
// Response dengan pagination sama dengan format getRegions()
// Menggunakan nama negara singkat
$results = Indonesia::searchWithAddress('Bakongan', null, null, null, 'ID');
use Aliziodev\IndonesiaRegions\Facades\Indonesia;
// Pencarian full text dengan default limit (15)
$results = Indonesia::searchWithFullText('Bakongan');
// Pencarian dengan limit kustom
$results = Indonesia::searchWithFullText('Bakongan', 25);
// Pencarian dengan nama negara singkat
$results = Indonesia::searchWithFullText(
term: 'Bakongan',
limit: 25,
countryName: 'ID'
);
// Response:
[
{
"code": "11.01.01.2001",
"province": "ACEH",
"city": "KAB. ACEH SELATAN",
"district": "BAKONGAN",
"village": "KEUDE BAKONGAN",
"postal_code": "23773",
"full_address": "KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, ID, 23773"
}
// ... more results
]
Metode ini selalu mengembalikan hasil pada level village. Kata kunci dapat berasal dari nama village, district, city, province, atau postal code, tetapi hasil akhirnya tetap berupa data village lengkap dengan hirarkinya.
Nilai countryName yang didukung hanya:
Indonesia (default)ID// Regular parameters
$region = Indonesia::findByCode('11.01.01.2001');
$region = Indonesia::findByCode('11.01.01.2001', ['code', 'name']);
// Named parameters (PHP 8.0+)
$region = Indonesia::findByCode(
code: '11.01.01.2001',
columns: ['code', 'name']
);
// Response:
{
"code": "11.01.01.2001",
"name": "KEUDE BAKONGAN",
"postal_code": "23773",
}
$provinces = Indonesia::getForSelect();
// Response:
{
"11": "ACEH",
"12": "SUMATERA UTARA",
"13": "SUMATERA BARAT"
// ... more provinces
}
// Get cities for select
$cities = Indonesia::getForSelect('11');
// Response:
{
"11.01": "KAB. ACEH SELATAN",
"11.02": "KAB. ACEH TENGGARA",
// ... more cities
}
$info = Indonesia::getRegionInfo('11.01.01.2001');
// Response:
{
"province": {
"code": "11",
"name": "ACEH"
},
"city": {
"code": "11.01",
"name": "KAB. ACEH SELATAN"
},
"district": {
"code": "11.01.01",
"name": "BAKONGAN"
},
"village": {
"code": "11.01.01.2001",
"name": "KEUDE BAKONGAN",
"postal_code": "23773"
},
"full_address": "KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, 23773"
}
// Menggunakan nama negara singkat
$info = Indonesia::getRegionInfo('11.01.01.2001', null, 'ID');
// Response akan menggunakan nama negara yang dipilih
"KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, ID, 23773"
$address = Indonesia::getFullAddress('11.01.01.2001');
// Response:
"KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, 23773"
// Menggunakan nama negara singkat
$address = Indonesia::getFullAddress('11.01.01.2001', 'ID');
// Response akan menggunakan nama negara yang dipilih
"KEUDE BAKONGAN, BAKONGAN, KAB. ACEH SELATAN, ACEH, ID, 23773"
$region = Indonesia::findByPostalCode('23773');
// Response:
{
"code": "11.01.01.2001",
"name": "KEUDE BAKONGAN",
"postal_code": "23773"
}
$isValid = Indonesia::validateCode('11.01.01.2001'); // true
$isValid = Indonesia::validateCode('11.99'); // false
$isValid = Indonesia::validateCode('11.12345'); // false
$type = Indonesia::getRegionType('11.01.01.2001'); // 'village'
$type = Indonesia::getRegionType('11.01.01'); // 'district'
$type = Indonesia::getRegionType('11.01'); // 'city'
$type = Indonesia::getRegionType('11'); // 'province'
php artisan indonesia-regions:clear-cache
Pengaturan cache dapat dikustomisasi melalui config/indonesia-regions.php.
searchWithFullText() pada level villageparentCode (string|null) : Kode wilayah parent (opsional)columns (array|null) : Kolom yang akan diambil (default: ['code', 'name', 'postal_code'])perPage (int|null) : Jumlah data per halaman untuk pagination (opsional)term (string) : Kata kunci pencariantype (string|null) : Tipe wilayah ('province'|'city'|'district'|'village')perPage (int|null) : Jumlah data per halaman untuk pagination (opsional)term (string) : Kata kunci pencariantype (string|null) : Tipe wilayah ('province'|'city'|'district'|'village')perPage (int|null) : Jumlah data per halaman untuk pagination (opsional)columns (array|null) : Kolom yang akan diambilcountryName (string|null) : Nama negara untuk alamat lengkap. Nilai yang didukung hanya Indonesia atau ID (default: Indonesia)term (string) : Kata kunci pencarianlimit (int|null) : Batas jumlah hasil pencarian (default: 15)countryName (string|null) : Nama negara untuk alamat lengkap. Nilai yang didukung hanya Indonesia atau ID (default: Indonesia)villagecode (string) : Kode wilayahcolumns (array|null) : Kolom yang akan diambil (default: ['*'])parentCode (string|null) : Kode wilayah parent (opsional)code (string) : Kode wilayahcolumns (array|null) : Kolom yang akan diambil (default: ['code', 'name', 'postal_code'])countryName (string|null) : Nama negara untuk alamat lengkap. Nilai yang didukung hanya Indonesia atau ID (default: Indonesia)villageCode (string) : Kode desa/kelurahancountryName (string|null) : Nama negara untuk alamat lengkap. Nilai yang didukung hanya Indonesia atau ID (default: Indonesia)postalCode (string) : Kode poscode (string) : Kode wilayah yang akan divalidasicode (string) : Kode wilayahData wilayah pada package ini pada dasarnya berasal dari cahyadsn/wilayah. Data tersebut kemudian diolah dan dipelihara lebih lanjut melalui repo upstream aliziodev/laravel-wilayah, lalu disinkronkan ke package ini.
Silakan buat issue atau pull request untuk kontribusi.
Package ini di bawah lisensi MIT.