Search by

ajangsupardi / laravel-postcode-id

ajangsupardi

This package is abandoned and no longer maintained. No replacement package was suggested.

Laravel package for seeding Indonesian address data (provinces, regencies, districts, villages) with postal codes from Pos Indonesia

Package info

github.com/ajangsupardi/laravel-postcode-id

pkg:composer/ajangsupardi/laravel-postcode-id

Statistics

Installs: 29

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.1.6 2026-07-21 10:22 UTC

This package is auto-updated.

Last update: 2026-10-22 11:03:39 UTC


README

Latest Stable Version License Total Downloads

Laravel package for Indonesian address data with postal codes — downloaded fresh from Pos Indonesia.

Features

  • Postal code lookup — Query villages by postal code with full address hierarchy
  • Fresh data — Downloads directly from Pos Indonesia, not static dumps
  • Idempotent seeders — Safe to run multiple times without duplicates
  • Hierarchical parsing — Province → Regency → District → Village with name normalization
  • Custom models — Extend default models or use your own
  • Laravel 11, 12, 13 — Modern PHP 8.3+

Installation

composer require ajangsupardi/laravel-postcode-id

Publish Configuration (optional)

php artisan vendor:publish --tag=postcode-config

Publish Migrations (optional)

php artisan vendor:publish --tag=postcode-migrations

Note: Migrations are automatically loaded by the service provider, so publishing is only needed if you want to modify the table structure.

Usage

1. Download Postcode Data

php artisan postcode:download

This command will download all postcode data from Pos Indonesia and save it as a CSV file.

2. Run Migrations & Seeder

php artisan migrate
php artisan postcode:seed

Or add it to your DatabaseSeeder.php:

use Ajangsupardi\PostcodeId\Database\Seeders\PostcodeSeeder;

public function run(): void
{
    $this->call([
        PostcodeSeeder::class,
    ]);
}

3. Auto-download & Seed

If you want to combine download and seed in a single step, you can call the download command before the seeder:

use Illuminate\Support\Facades\Artisan;

$storagePath = config('postcode.storage_path');
if (! file_exists($storagePath.'/kodepos.csv')) {
    Artisan::call('postcode:download');
}

Postal Code Lookup

The main feature — find any Indonesian address by postal code:

use Ajangsupardi\PostcodeId\Models\Village;

// Village by postal code
$village = Village::where('postal_code', '60111')->first();

// With full address hierarchy
$village = Village::with('district.regency.province')
    ->where('postal_code', '60111')
    ->first();

// Result: Gubeng → Kota Surabaya → Jawa Timur
// Search by village name
$villages = Village::where('name', 'LIKE', '%Gubeng%')
    ->with('district.regency')
    ->get();

Database Tables

This package creates 4 tables:

Table Description
provinces Province data (id, name, code)
regencies Regency/city data (id, province_id, name)
districts District/sub-district data (id, regency_id, name)
villages Village data (id, district_id, name, postal_code)

Configuration

Edit config/postcode.php:

return [
    // CSV file storage path
    'storage_path' => storage_path('app/postcode'),

    // Database table prefix (null = no prefix)
    'table_prefix' => null,

    // Custom models
    'models' => [
        'province' => Ajangsupardi\PostcodeId\Models\Province::class,
        'regency'  => Ajangsupardi\PostcodeId\Models\Regency::class,
        'district' => Ajangsupardi\PostcodeId\Models\District::class,
        'village'  => Ajangsupardi\PostcodeId\Models\Village::class,
    ],

    // HTTP client settings
    'http' => [
        'timeout' => 60,
        'connect_timeout' => 10,
        'retry' => 3,
        'retry_delay' => 1000,
        'user_agent' => 'Mozilla/5.0 (compatible; LaravelPostcodeId/1.0)',
    ],
];

Custom Models

You can extend the default models to add columns or relationships:

namespace App\Models;

use Ajangsupardi\PostcodeId\Models\Province as BaseProvince;

class Province extends BaseProvince
{
    protected $fillable = ['name', 'code', 'your_custom_field'];

    // Add custom relationships or methods
}

Then update the configuration:

'models' => [
    'province' => App\Models\Province::class,
],

Table Prefix

If you want to use a prefix for your tables:

'table_prefix' => 'postcode_',

This will create tables: postcode_provinces, postcode_regencies, postcode_districts, postcode_villages.

Example Queries

use Ajangsupardi\PostcodeId\Models\Province;
use Ajangsupardi\PostcodeId\Models\Village;

// Get all provinces
$provinces = Province::all();

// Get regencies in East Java
$regencies = Province::where('name', 'Jawa Timur')
    ->first()
    ->regencies;

// Find a village by postal code
$village = Village::where('postal_code', '60111')->first();

// Get full address hierarchy from village to province
$village = Village::with('district.regency.province')
    ->where('postal_code', '60111')
    ->first();

Requirements

  • PHP ^8.3
  • Laravel ^11.0 / ^12.0 / ^13.0

Changelog

v1.1.6

  • Fix progress bar not displaying in terminal during postcode:seed

v1.1.5

  • Fix postcode:seed hanging on PostgreSQL — remove transaction wrapper that caused deadlock

v1.1.4

  • Fix postcode:seed hanging indefinitely — use Artisan::call() instead of Command::call() to correctly invoke seeder

v1.1.3

  • Add progress bar to all seeders for visual feedback during bulk operations

v1.1.2

  • Fix postcode:download failing on transient network errors — retry now handles cURL connection exceptions

v1.1.1

  • Fix VillageSeeder hanging/timing out on PostgreSQL — foreign key triggers are temporarily disabled during bulk insert

v1.1.0

  • Added postcode:seed artisan command to fix shell escaping bug on Linux

v1.0.0

  • Initial release — download, parse, and seed Indonesian address data with postal codes

License

MIT License. See LICENSE for more information.