Skip to content

Concern Model (Trait)

Laravel Nusa menyediakan kumpulan trait (concern) yang dapat digunakan kembali untuk menambahkan fungsionalitas wilayah administratif Indonesia ke model Anda sendiri. Trait ini memudahkan integrasi fitur berbasis lokasi ke dalam model aplikasi Anda.

Ringkasan

Concern model terletak di dalam namespace Creasi\Nusa\Models\Concerns dan menyediakan berbagai jenis relasi dan fungsionalitas:

Trait Relasi

  • WithProvince - Menambahkan relasi belongsTo ke provinsi
  • WithRegency - Menambahkan relasi belongsTo ke kabupaten/kota
  • WithDistrict - Menambahkan relasi belongsTo ke kecamatan
  • WithVillage - Menambahkan relasi belongsTo ke desa/kelurahan
  • WithDistricts - Menambahkan relasi hasMany ke kecamatan
  • WithVillages - Menambahkan relasi hasMany ke desa/kelurahan dengan kode pos

Trait Manajemen Alamat

Trait Geografis

Contoh Penggunaan Umum

Profil Pengguna dengan Lokasi

php
use Creasi\Nusa\Models\Concerns\{WithProvince, WithRegency, WithDistrict, WithVillage};

class UserProfile extends Model
{
    use WithProvince, WithRegency, WithDistrict, WithVillage;
    
    protected $fillable = [
        'name', 'email', 
        'province_code', 'regency_code', 'district_code', 'village_code'
    ];
}

// Penggunaan
$profile = UserProfile::with(['province', 'regency', 'district', 'village'])->first();
echo "Location: {$profile->village->name}, {$profile->district->name}, {$profile->regency->name}, {$profile->province->name}";

Lokasi Bisnis

php
use Creasi\Nusa\Models\Concerns\{WithAddress, WithCoordinate};

class Store extends Model
{
    use WithAddress, WithCoordinate;
    
    protected $fillable = [
        'name', 'description', 'latitude', 'longitude'
    ];
}

// Penggunaan
$store = Store::with('address')->first();
echo "Store: {$store->name} at {$store->latitude}, {$store->longitude}";

Manajemen Regional

php
use Creasi\Nusa\Models\Concerns\{WithProvince, WithDistricts, WithVillages};

class RegionalOffice extends Model
{
    use WithProvince, WithDistricts, WithVillages;
    
    protected $fillable = ['name', 'province_code'];
}

// Penggunaan
$office = RegionalOffice::with(['province', 'districts', 'villages'])->first();
echo "Office covers {$office->districts->count()} districts and {$office->villages->count()} villages";

Instalasi dan Pengaturan

1. Gunakan Trait di Model Anda

Cukup tambahkan pernyataan use untuk trait yang Anda butuhkan:

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Creasi\Nusa\Models\Concerns\WithVillage;

class Customer extends Model
{
    use WithVillage;
    
    protected $fillable = ['name', 'email', 'village_code'];
}

2. Migrasi Database

Pastikan tabel database Anda memiliki kolom foreign key yang sesuai:

php
Schema::create('customers', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('email');
    $table->string('village_code')->nullable();
    $table->timestamps();
    
    // Optional: Add foreign key constraint
    $table->foreign('village_code')
          ->references('code')
          ->on('villages')
          ->onDelete('set null');
});

3. Kustomisasi Nama Foreign Key

Anda dapat mengkustomisasi nama kolom foreign key dengan mendefinisikan properti:

php
class Customer extends Model
{
    use WithVillage;
    
    protected $villageKey = 'customer_village_code';
    protected $fillable = ['name', 'email', 'customer_village_code'];
}

Penggunaan Lanjutan

Dukungan Alamat Ganda

php
use Creasi\Nusa\Models\Concerns\WithAddresses;

class Company extends Model
{
    use WithAddresses;
}

// Usage
$company = Company::first();
$company->addresses()->create([
    'type' => 'headquarters',
    'province_code' => '33',
    'regency_code' => '33.75',
    'district_code' => '33.75.01',
    'village_code' => '33.75.01.1002',
    'address_line' => 'Jl. Merdeka No. 123'
]);

Kueri Geografis

php
use Creasi\Nusa\Models\Concerns\WithCoordinate;

class Event extends Model
{
    use WithCoordinate;
}

// Find events within a radius
$nearbyEvents = Event::selectRaw('*, (
    6371 * acos(
        cos(radians(?)) * cos(radians(latitude)) * 
        cos(radians(longitude) - radians(?)) + 
        sin(radians(?)) * sin(radians(latitude))
    )
) AS distance', [$lat, $lng, $lat])
->having('distance', '<', 10)
->orderBy('distance')
->get();

Praktik Terbaik

1. Gunakan Trait yang Sesuai

Pilih trait berdasarkan kebutuhan model Anda:

  • Gunakan WithVillage untuk lokasi paling spesifik
  • Gunakan WithProvince untuk pengelompokan regional
  • Gunakan WithAddresses untuk model yang dapat memiliki banyak lokasi

2. Eager Loading

Selalu lakukan eager load pada relasi untuk menghindari kueri N+1:

php
$pelanggan = Pelanggan::with(['village.district.regency.province'])->get();

3. Validasi

Validasi kode administratif dalam form request Anda:

php
public function rules()
{
    return [
        'village_code' => 'required|exists:nusa.villages,code',
        'district_code' => 'required|exists:nusa.districts,code',
        'regency_code' => 'required|exists:nusa.regencies,code',
        'province_code' => 'required|exists:nusa.provinces,code',
    ];
}

Dokumentasi Terkait

Released under the MIT License.