baleethai/filament-thailand-location-picker

FilamentPHP plugin for picking Thailand region/province/district/subdistrict

Maintainers

Package info

github.com/baleethai/filament-thailand-location-picker

pkg:composer/baleethai/filament-thailand-location-picker

Transparency log

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-08-10 10:35 UTC

This package is auto-updated.

Last update: 2026-08-10 10:41:09 UTC


README

FilamentPHP v5 plugin สำหรับเลือกที่อยู่ในประเทศไทยแบบ cascading dropdown — ภาค (Region) → จังหวัด (Province) → อำเภอ (District) → ตำบล (Subdistrict) — พร้อมข้อมูลที่อยู่ครบทั้งประเทศและรหัสไปรษณีย์ ไม่ต้องพึ่ง API ภายนอก

ทำไมต้องใช้

ทุกโปรเจกต์ที่มีฟอร์มที่อยู่ไทย มักต้องทำงานซ้ำ ๆ กัน: สร้างตารางภาค/จังหวัด/อำเภอ/ตำบล, หา seed data, และเขียน reactive logic ให้ dropdown แต่ละระดับกรองตามระดับก่อนหน้า แพ็กเกจนี้รวมทุกอย่างไว้ให้ ติดตั้งครั้งเดียวใช้ได้ทุกโปรเจกต์

Features

  • Cascading select 4 ระดับ: ภาค → จังหวัด → อำเภอ → ตำบล (reactive ด้วย Livewire, กรองตัวเลือกอัตโนมัติเมื่อระดับก่อนหน้าถูกเลือก)
  • ข้อมูลที่อยู่ครบทั้งประเทศ พร้อมใช้ทันทีผ่าน php artisan thailand:seed (6 ภาค, 77 จังหวัด, 930 อำเภอ, 7,452 ตำบล)
  • เติมรหัสไปรษณีย์ให้อัตโนมัติเมื่อเลือกตำบล
  • รองรับสองภาษา (th / en) ตั้งค่าได้ทั้งระดับ global และรายฟิลด์ พร้อมคำแปล label ของฟิลด์ให้ทั้ง en/th ในตัว (publish แก้ไขเองได้)
  • เปิด/ปิดฟิลด์ ภาค (Region) ได้ทั้งระดับ global (config) และรายฟิลด์
  • Component สำเร็จรูป ThailandLocation (ที่อยู่ + 4 dropdown + รหัสไปรษณีย์ในตัวเดียว) หรือใช้ select แต่ละตัวแยกกันเพื่อคุมเลย์เอาต์เอง
  • Table column ThailandLocationColumn แสดงที่อยู่แบบเต็ม (ตำบล, อำเภอ, จังหวัด, ภาค) จาก relationship เดียว พร้อม eager loading ป้องกัน N+1
  • ชื่อตารางและชื่อฟิลด์ configurable ผ่าน config/thailand-plugin.php

Requirements

  • PHP 8.2+
  • Laravel (illuminate/database, illuminate/support) 11.x, 12.x หรือ 13.x
  • FilamentPHP 5.x

Installation

composer require baleethai/filament-thailand-location-picker

Publish และรัน migrations:

php artisan vendor:publish --tag="thailand-plugin-migrations"
php artisan migrate

Seed ข้อมูลที่อยู่ทั่วประเทศ:

php artisan thailand:seed

(ถ้าต้องการแก้ไข config เช่นชื่อตารางหรือ locale เริ่มต้น ให้ publish config เพิ่ม)

php artisan vendor:publish --tag="thailand-plugin-config"

ลงทะเบียน Plugin ใน Panel (ถ้าต้องการ)

use Baleethai\ThailandPlugin\ThailandPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            ThailandPlugin::make(),
        ]);
}

Usage

1. วิธีที่ง่ายที่สุด — component เดียวจบ

ThailandLocation วาง address line 1/2, ภาค, จังหวัด, อำเภอ, ตำบล และรหัสไปรษณีย์ ให้ในครั้งเดียว พร้อม cascading logic ระหว่างกันทั้งหมด:

use Baleethai\ThailandPlugin\Forms\Components\ThailandLocation;

public static function form(Schema $schema): Schema
{
    return $schema->components([
        ThailandLocation::make(),
    ]);
}

ค่าเริ่มต้นจะเก็บลงฟิลด์เหล่านี้:

Field Default column
Address line 1 address_line_1
Address line 2 address_line_2
Region (ภาค) geo_id
Province (จังหวัด) province_id
District (อำเภอ) district_id
Subdistrict (ตำบล) subdistrict_id
Zip code zip_code

กำหนดชื่อฟิลด์เอง หรือปิดใช้งานบางอย่างได้:

ThailandLocation::make()
    ->geoField('region_id')
    ->provinceField('province_id')
    ->districtField('district_id')
    ->subdistrictField('subdistrict_id')
    ->zipField('postal_code')
    ->required()
    ->searchable()
    ->locale('en'),

ปิดฟิลด์ ภาค (Region) ทิ้งไปได้ทั้งแบบรายฟิลด์ หรือตั้ง default ผ่าน config:

ThailandLocation::make()
    ->geoEnabled(false),

2. ใช้ select แยกทีละตัว — คุม layout เอง

ใช้เมื่อไม่ต้องการ address line / zip code ในตัว หรือต้องการจัดวางเอง โดยแต่ละ select ต้องบอกว่าอ้างอิงฟิลด์ระดับก่อนหน้าชื่ออะไร:

use Baleethai\ThailandPlugin\Forms\Components\GeoSelect;
use Baleethai\ThailandPlugin\Forms\Components\ProvinceSelect;
use Baleethai\ThailandPlugin\Forms\Components\DistrictSelect;
use Baleethai\ThailandPlugin\Forms\Components\SubdistrictSelect;
use Filament\Schemas\Components\Grid;

Grid::make(4)->schema([
    GeoSelect::make('geo_id')
        ->required(),

    ProvinceSelect::make('province_id')
        ->geoField('geo_id')
        ->required(),

    DistrictSelect::make('district_id')
        ->provinceField('province_id')
        ->required(),

    SubdistrictSelect::make('subdistrict_id')
        ->districtField('district_id')
        ->zipField('zip_code') // เติมรหัสไปรษณีย์อัตโนมัติเมื่อเลือก, ไม่ใส่ก็ได้ถ้าไม่ต้องการ
        ->required(),
]),

3. แสดงในตาราง (Table Column)

ThailandLocationColumn อ่านค่าจาก relationship ที่ชี้ไปยัง Subdistrict แล้วไล่ขึ้นไปแสดงตำบล, อำเภอ, จังหวัด, ภาค รวมกันเป็นข้อความเดียว โดย default จะเดา relationship name จากชื่อคอลัมน์ (ตัดท้าย _id ออก) หรือระบุเองก็ได้:

use Baleethai\ThailandPlugin\Tables\Columns\ThailandLocationColumn;

ThailandLocationColumn::make('subdistrict_id')
    ->label('ที่อยู่')
    ->subdistrictRelationship('subdistrict'), // optional ถ้าชื่อ relationship ไม่ตรงกับที่เดาไว้

4. ภาษา (Locale)

Locale เริ่มต้นมาจาก config('thailand-plugin.locale') (ค่า default คือ th) แต่ override ได้ทั้งใน ThailandLocation, select แต่ละตัว หรือ ThailandLocationColumn:

GeoSelect::make('geo_id')->locale('en');
ThailandLocation::make()->locale('en');
ThailandLocationColumn::make('subdistrict_id')->locale('en');

Locale ข้างบนนี้ควบคุมว่าจะดึงชื่อจากคอลัมน์ name_th หรือ name_en (ข้อมูลในฐานข้อมูล) — คนละส่วนกับภาษาที่ label ของฟิลด์ (เช่น "Region", "Province") แสดงผล ซึ่งมาจาก app locale (App::getLocale()) ของโปรเจกต์ตามปกติ แพ็กเกจนี้มีคำแปลให้ทั้ง en และ th ในตัว ถ้าต้องการแก้ไขคำแปลเอง ให้ publish ไฟล์ translation ออกมา:

php artisan vendor:publish --tag="thailand-plugin-translations"

เปิด/ปิดฟิลด์ ภาค (Region)

ปิดใช้งานฟิลด์ ภาค ทั้งโปรเจกต์ได้ผ่าน config, หรือ override เป็นรายฟิลด์ด้วย ->geoEnabled(false) (ดูตัวอย่างในหัวข้อก่อนหน้า) เมื่อปิดใช้งาน ProvinceSelect จะแสดงทุกจังหวัดโดยไม่กรองตามภาค

Configuration

// config/thailand-plugin.php

return [
    'tables' => [
        'geos' => 'geos',
        'provinces' => 'provinces',
        'districts' => 'districts',
        'subdistricts' => 'subdistricts',
    ],

    'searchable' => true,

    // 'th' | 'en'
    'locale' => 'th',

    // Show/hide the Region (Geo) select in the ThailandLocation component.
    'enable_geo' => true,
];

Data Structure

Table Columns Rows after seeding
geos id, name_th, name_en 6
provinces id, geo_id, name_th, name_en 77
districts id, province_id, name_th, name_en 930
subdistricts id, district_id, name_th, name_en, zip_code 7,452

ชื่อตารางแก้ได้ผ่าน config('thailand-plugin.tables') — โมเดลทุกตัว (Geo, Province, District, Subdistrict) จะ resolve ชื่อตารางจาก config นี้เสมอ

Development

cd packages/baleethai/filament-thailand-location-picker
composer install
vendor/bin/pest

License

MIT License.