creasi / laravel-nusa
A Laravel package that aim to provide Indonesia' Administrative Data
Fund package maintenance!
creasico
Installs: 5 608
Dependents: 2
Suggesters: 0
Security: 0
Stars: 9
Watchers: 5
Forks: 3
Open Issues: 1
Requires
- php: ^8.1
- ext-sqlite3: *
- laravel/framework: ^9.0|^10.0|^11.0
Requires (Dev)
- composer-runtime-api: *
- laravel/pint: ^1.1
- nunomaduro/collision: ^7.4|^8.0
- orchestra/testbench: ^8.5|^9.0
README
Creasi Nusa
Simple library aims to provide Indonesia Administrative Region Data based including the coordinates and postal codes, that easily integrated with our laravel project.
Requirements
- PHP
>=v8.1
withphp-sqlite3
extension - Laravel
>=10.0
Why?
Why don't just use existsing laravolt/indonesia, you may ask? That packages have been around for quite sometimes and already 've been used by hundreds of people, indeed. But, we need a package that ready-to-use once its installed.
I've been using edwardsamuel/Wilayah-Administratif-Indonesia for a while and put some contributions there, but it seems no longer maintained since 2018. More over its built for python not PHP.
That's why we choose cahyadsn/wilayah it has robust and strong database in terms of legality, but its not actually a package that can be installed as dependency. By that said, it has some work to-do.
We also found that w3appdev/kodepos provides better database structures that can easily mapped with databases from cahyadsn/wilayah in single query.
Our takes for the words "easily integrated" and "ready-to-use once its installed" means we shouldn't dealing with the data migration and seeding, hence Indonesia isn't a small country, right? running seeder for such amount of data can takes quite some times to proceed let alone the app seeder.
Why PHP >=8.1
and Laravel >=10.0
, you may ask? Because, why not!
Installation
composer require creasi/laravel-nusa
That's all
Roadmaps
- Basic Models
- Provinces, includes
laltitude
,longitude
andcoordinates
- Regencies, includes
laltitude
,longitude
andcoordinates
- Districts
- Vilages, include
postal_code
- Provinces, includes
- Routing
Usage
Thankfully Laravel provides us convenience way to have some sort of "relations" regardless of the database engine. So we can have this administrative data shipped in sqlite
data and once we install it, then all we need is use it from our project with convenience of eloquent models.
ReSTful API
-
Get all provinces
GET {APP_URL}/nusa/provinces
-
Query Params :
-
Example :
-
GET http://localhost:8000/nusa/provinces
{ "data": [ { "code": 33, "name": "Jawa Tengah", "latitude": -6.9934809206806, "longitude": 110.42024335421, "coordinates": [...], "postal_codes": [...], }, { ... } ], "links": { "first": "http://localhost:8000/nusa/provinces?page=1", "last": "http://localhost:8000/nusa/provinces?page=3", "prev": null, "next": "http://localhost:8000/nusa/provinces?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 3, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/provinces?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost/nusa/provinces?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/provinces", "per_page": 15, "to": 15, "total": 34 } }
-
-
-
Show a province
GET {APP_URL}/nusa/provinces/{province}
- Route Param :
{province}
province code - Example :
-
GET http://localhost:8000/nusa/provinces/33
{ "data": { "code": 33, "name": "Jawa Tengah", "latitude": -6.9934809206806, "longitude": 110.42024335421, "coordinates": [...], "postal_codes": [...], }, "meta": {} }
-
- Route Param :
-
Get all regencies in a province
GET {APP_URL}/nusa/provinces/{province}/regencies
- Route Param :
{province}
province code - Example :
-
GET http://localhost:8000/nusa/provinces/33/regencies
{ "data": [ { "code": 3375, "province_code": 33, "name": "Kota Pekalongan", "latitude": -6.8969497174987, "longitude": 109.66208089654, "coordinates": [...], "postal_codes": [...], }, { ... } ], "links": { "first": "http://localhost:8000/nusa/provinces/33/regencies?page=1", "last": "http://localhost:8000/nusa/provinces/33/regencies?page=3", "prev": null, "next": "http://localhost:8000/nusa/provinces/33/regencies?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 3, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/provinces/33/regencies?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost/nusa/provinces/33/regencies?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/provinces/33/regencies", "per_page": 15, "to": 15, "total": 35 } }
-
- Route Param :
-
Get all districts in a province
GET {APP_URL}/nusa/provinces/{province}/districts
- Route Param :
{province}
province code - Example :
-
GET http://localhost:8000/nusa/provinces/33/districts
{ "data": [ { "code": 330101, "regency_code": 3301, "province_code": 33, "name": "Kedungreja", "postal_codes": [ 53263 ] }, { ... } ], "links": { "first": "http://localhost:8000/nusa/provinces/33/districts?page=1", "last": "http://localhost:8000/nusa/provinces/33/districts?page=39", "prev": null, "next": "http://localhost/nusa/provinces/33/districts?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 39, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/provinces/33/districts?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost/nusa/provinces/33/districts?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/provinces/33/districts", "per_page": 15, "to": 15, "total": 576 } }
-
- Route Param :
-
Get all villages in a province
GET {APP_URL}/nusa/provinces/{province}/villages
- Route Param :
{province}
province code - Example :
-
GET http://localhost:8000/nusa/provinces/33/villages
{ "data": [ { "code": 3301012001, "district_code": 330101, "regency_code": 3301, "province_code": 33, "name": "Tambakreja", "postal_code": 53263, }, { ... } ], "links": { "first": "http://localhost:8000/nusa/provinces/33/villages?page=1", "last": "http://localhost:8000/nusa/provinces/33/villages?page=571", "prev": null, "next": "http://localhost:8000/nusa/provinces/33/villages?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 571, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/provinces/33/villages?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost:8000/nusa/provinces/33/villages?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/provinces/33/villages", "per_page": 15, "to": 15, "total": 8562 } }
-
- Route Param :
-
Get all regencies
GET {APP_URL}/nusa/regencies
-
Query Params :
-
Example :
-
GET http://localhost:8000/nusa/regencies
{ "data": [ { "code": 3375, "province_code": 33, "name": "Kota Pekalongan", "latitude": -6.8969497174987, "longitude": 109.66208089654, "coordinates": [...], "postal_codes": [...], }, { ... } ], "links": { "first": "http://localhost:8000/nusa/regencies?page=1", "last": "http://localhost:8000/nusa/regencies?page=35", "prev": null, "next": "http://localhost:8000/nusa/regencies?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 35, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/regencies?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost/nusa/regencies?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/regencies", "per_page": 15, "to": 15, "total": 514 } }
-
-
-
Show a regency
GET {APP_URL}/nusa/regencies/{regency}
- Route Param :
{regency}
regency code - Example :
-
GET http://localhost:8000/nusa/regencies/3375
{ "data": { "code": 3375, "province_code": 33, "name": "Kota Pekalongan", "latitude": -6.8969497174987, "longitude": 109.66208089654, "coordinates": [...], "postal_codes": [...], }, "meta": {} }
-
- Route Param :
-
Get all districts in a regency
GET {APP_URL}/nusa/regencies/{regency}/districts
- Route Param :
{regency}
regency code - Example :
-
GET http://localhost:8000/nusa/regencies/3375/districts
{ "data": [ { "code": 337501, "regency_code": 3375, "province_code": 33, "name": "Pekalongan Barat", "postal_codes": [ 51111 51112 51113 51116 51117 51151 ] }, { ... } ], "links": { "first": "http://localhost:8000/nusa/regencies/3375/districts?page=1", "last": "http://localhost:8000/nusa/regencies/3375/districts?page=1", "prev": null, "next": null, }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/regencies/3375/districts?page=1", "label": "1", "active": true, }, { ... }, { "url": null, "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/regencies/3375/districts", "per_page": 15, "to": 4, "total": 4 } }
-
- Route Param :
-
Get all villages in a regency
GET {APP_URL}/nusa/regencies/{regency}/villages
- Route Param :
{regency}
regency code - Example :
-
GET http://localhost:8000/nusa/regencies/3375/villages
{ "data": [ { "code": 3375011002, "district_code": 337501, "regency_code": 3375, "province_code": 33, "name": "Medono", "postal_code": 51111, }, { ... } ], "links": { "first": "http://localhost:8000/nusa/regencies/3375/villages?page=1", "last": "http://localhost:8000/nusa/regencies/3375/villages?page=2", "prev": null, "next": "http://localhost:8000/nusa/regencies/3375/villages?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 2, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/regencies/3375/villages?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost:8000/nusa/regencies/3375/villages?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/regencies/3375/villages", "per_page": 15, "to": 15, "total": 27 } }
-
- Route Param :
-
Get all districts
GET {APP_URL}/nusa/districts
-
Query Params :
-
Example :
-
GET http://localhost:8000/nusa/districts
{ "data": [ { "code": 110101, "regency_code": 1101, "province_code": 11, "name": "Bakongan", "postal_codes": [ 23773 ], }, { ... } ], "links": { "first": "http://localhost:8000/nusa/districts?page=1", "last": "http://localhost:8000/nusa/districts?page=485", "prev": null, "next": "http://localhost:8000/nusa/districts?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 485, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/districts?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost:8000/nusa/districts?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/districts", "per_page": 15, "to": 15, "total": 7266 } }
-
-
-
Show a district
GET {APP_URL}/nusa/districts/{district}
- Route Param :
{district}
district code - Example :
-
GET http://localhost:8000/nusa/districts/337503
{ "data": { "code": 337503, "regency_code": 3375, "province_code": 33, "name": "Pekalongan Utara", "postal_codes": [ 51141 51143 51146 51147 51148 51149 ], }, "meta": {} }
-
- Route Param :
-
Get all villages in a district
GET {APP_URL}/nusa/districts/{district}/villages
- Route Param :
{district}
district code - Example :
-
GET http://localhost:8000/nusa/districts/337503/villages
{ "data": [ { "code": 3375031002, "district_code": 337503, "regency_code": 3375, "province_code": 33, "name": "Krapyak", "postal_code": 51147, }, { ... } ], "links": { "first": "http://localhost:8000/nusa/districts/337503/villages?page=1", "last": "http://localhost:8000/nusa/districts/337503/villages?page=1", "prev": null, "next": null, }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/districts/337503/villages?page=1", "label": "1", "active": true, }, { ... }, { "url": null, "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/districts/337503/villages", "per_page": 15, "to": 7, "total": 7 } }
-
- Route Param :
-
Get all villages
GET {APP_URL}/nusa/villages
-
Query Params :
-
Example :
-
GET http://localhost:8000/nusa/villages
{ "data": [ { "code": 1101012001, "district_code": 110101, "regency_code": 1101, "province_code": 11, "name": "Keude Bakongan", "postal_code": 23773, }, { ... } ], "links": { "first": "http://localhost:8000/nusa/villages?page=1", "last": "http://localhost:8000/nusa/villages?page=5565", "prev": null, "next": "http://localhost:8000/nusa/villages?page=2", }, "meta": { "current_page": 1, "from": 1, "last_page": 5565, "links": [ { "url": null, "label": "« Previous", "active": false, }, { "url": "http://localhost:8000/nusa/villages?page=1", "label": "1", "active": true, }, { ... }, { "url": "http://localhost:8000/nusa/villages?page=2", "label": "Next »", "active": false, }, ], "path": "http://localhost:8000/nusa/villages", "per_page": 15, "to": 15, "total": 83467 } }
-
-
-
Get a village
GET {APP_URL}/nusa/villages/{village}
- Route Param :
{village}
village code - Example :
-
GET http://localhost:8000/nusa/villages/3375031006
{ "data": { "code": 3375031006, "district_code": 337503, "regency_code": 3375, "province_code": 33, "name": "Padukuhan Kraton", "postal_code": 51146, }, "meta": {} }
-
- Route Param :
Models
This library comes with 4 primary models as follows :
Creasi\Nusa\Models\Province
Creasi\Nusa\Models\Regency
Creasi\Nusa\Models\District
Creasi\Nusa\Models\Village
Every models comes with similar interfaces, which mean every model has code
and name
field in it, you can also use search()
scope method to query model either by code
or name
. e.g:
use Creasi\Nusa\Models\Province; $province = Province::search(33)->first(); // or $province = Province::search('Jawa Tengah')->first();
Please note that only Province
and Regency
that comes with latitude
, longitude
and coordinates
data, while Village
comes with postal_code
. That's due to what cahyadsn/wilayah provide us.
In that regard we expect that Province
, Regency
and District
should have access of any postal_codes
that available within those area, and we believe that might be helpful in some cases. And there you go
// Retrieve distict list of postal codes available in the province $province->postal_codes;
Base on our experiences developing huge variety of products, the most use cases we need such a data is to fill up address form. But the requirement is might be vary on every single project. For that reason we also provide the bare minimun of Address
model that use your default db connection and can easily extended to comply with project's requirement.
In that case you might wanna use our WithAddresses
or WithAdress
trait to your exitsting model, like so
use Creasi\Nusa\Contracts\HasAddresses; use Creasi\Nusa\Models\Concerns\WithAddresses; class User extends Model implements HasAddresses { use WithAddresses; }
To be able to use Address
model, all you need is to publish the migration, like so
php artisan vendor:publish --tag creasi-migrations
Then simply run artisan migrate
to apply the additional migrations.
Databases
The database structure documentation please consult to database/README.md
.
Customization
By default, nusa
will add another database.connections
config to your project and use it as main database for all nusa
's models, and you can customize it anyway.
-
Publish
nusa
's config by running the following commands./artisan vendor:publish --tag creasi-nusa-config
-
Add new
database.connections
with key of yourcreasi.nusa.connection
, say you have// config/nusa.php return [ 'connection' => 'indonesia', ];
So, you'll need
// config/database.php return [ 'connections' => [ 'indonesia' => [ // ... ] ], ];
In term of extending Address
model, please a look at creasi.nusa.addressable
config if you wanna use your own implementation of Address
model.
Notes
As of now, only connection
name and table
names are available to customize, also we only test it using sqlite
driver. Let us know if you had any issue using another database drivers.
Contributing
-
Clone the repo and
cd
into itgit clone --recurse-submodules git@github.com:creasico/laravel-nusa.git
-
Install dependencies
composer install
-
Create new database, by default we use the following configuration :
dbname
:nusantara
dbhost
:127.0.0.1
dbuser
:root
dbpass
:secret
mysql -e 'create database nusantara;'
-
Last but not least, run
db:import
commandcomposer db:import
If you were using different configuration you can edit this file but please don't submit your changes.
Once you've done with your meaningful contributions, run the following command to ensure everythings is works as expected.
composer test
Notes
- Commit Convention: This project follows Conventional Commits using @commitlint/config-conventional as standart, so make sure you install its npm dependencies.
- Code Style: This project uses
Laravel Pint
withlaravel
preset as coding standard, so make sure you follow the rules.
Credits
License
This library is open-sourced software licensed under MIT license.