Belajar Laravel #28: Filament — Admin Panel Cepat dengan Resource, Form, Table, dan Action

Di episode #27 saya sempat berpikir: setiap kali butuh halaman admin — CRUD sederhana, tabel data, form — saya selalu mulai dari nol. Route, controller, validasi, view, ulang lagi. Proyek musim 1 di episode #24 saya kerjakan manual, dan saat itu saya sadar sebagian besar waktunya habis untuk pekerjaan berulang yang tidak menambah nilai. Filament lahir dari keluhan yang sama: kenapa panel admin harus ditulis tangan tiap proyek?

Filament itu apa, sebenarnya

Filament adalah kumpulan komponen untuk membangun panel admin di Laravel — sekarang berada di versi v5 (rilis 16 Januari 2026, dan saat saya menulis catatan ini versi terbarunya v5.11.2, 7 November 2026). Syaratnya: PHP 8.2+, Laravel 11.28 atau lebih baru, dan Filament v5 dibangun di atas Livewire v4. Kalau kamu membaca ini dengan versi berbeda, cek dulu dokumentasi resminya.

Saya suka menyebut Filament sebagai “Laravel yang sudah punya kantor administrasi”. Model Eloquent sudah kamu tulis, tinggal bilang ke Filament: “tabel ini punya kolom ini, form-nya ini, dan tombol aksinya begini” — sisanya dia kerjakan. Konsep intinya cuma empat: resource, form builder, table, dan action. Setelah empat ini paham, hampir semua panel admin bisa dirakit.

Resource: satu file untuk satu model

Di musim 1 saya membuat PostController berisi metode index, create, store, show, edit, update, destroy. Filament menggantinya dengan satu kelas resource. Lewat Artisan:

php artisan make:filament-resource Post

Perintah ini membuat satu file kelas di app/Filament/Resources/. Yang menarik bagian saya: Filament bisa meng-generate field form dan kolom tabel dari skema migration-mu (ada pilihan “generate” saat perintah dijalankan). Saya mencobanya, hasilnya belum tentu sempurna, tapi 70% kebutuhan dasar sudah terisi — dan sisanya tinggal disesuaikan tangan. Satu resource otomatis membawa empat halaman sekaligus: daftar (index), buat baru, edit, dan detail — plus tautannya masuk ke menu navigasi panel. Dulu empat halaman itu saya tulis sendiri-sendiri.

Form builder: deklaratif, bukan imperative

Di controller manual, validasi saya tulis sebagai array aturan, lalu view-nya satu-satu input-nya. Di Filament, form dideklarasikan dalam metode form():

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Section::make('Judul & Isi')
                ->schema([
                    TextInput::make('title')
                        ->required()
                        ->maxLength(255),
                    RichEditor::make('body')
                        ->columnSpanFull(),
                ]),
            Select::make('category_id')
                ->relationship('category', 'name')
                ->required(),
            Toggle::make('is_published')
                ->default(false),
        ])
        ->columns(2);
}

Yang saya catat: validasi ikut menempel di field-nya (->required(), ->maxLength()) — jadi tidak ada lagi array validasi yang terpisah dari input-nya dan akhirnya tidak sinkron. Filament juga menyediakan tipe field banyak: TextInput, Textarea, RichEditor, Select, Toggle, DatePicker, FileUpload, dan lainnya. Untuk field yang berkaitan model lain, ->relationship('category', 'name') otomatis menampilkan pilihan dari tabel category — ini yang dulu saya tulis manual dengan loop di select.

Table: kolom, filter, dan pencarian

Metode table() mendefinisikan tampilan data. Pernah saya menulis query lalu view tabel lalu paginasi sendiri-sendiri? Di sini cukup:

public static function table(Table $table): Table
{
    return $table
        ->columns([
            TextColumn::make('title')
                ->searchable()
                ->limit(40),
            TextColumn::make('category.name')
                ->badge(),
            ToggleColumn::make('is_published'),
            TextColumn::make('created_at')
                ->dateTime('d M Y'),
        ])
        ->filters([
            SelectFilter::make('category')
                ->relationship('category', 'name'),
            Filter::make('published')
                ->query(fn ($query) => $query->where('is_published', true)),
        ])
        ->actions([
            EditAction::make(),
        ])
        ->bulkActions([
            BulkActionGroup::make([
                DeleteBulkAction::make(),
            ]),
        ]);
}

Dua hal yang langsung saya manfaatkan: ->searchable() membuat pencarian instan di kolom itu (Livewire yang menanganinya, tidak perlu tulis endpoint), dan ->badge() menampilkan nama kategori sebagai badge. Filter tinggal dideklarasikan — pilihan dropdown-nya diambil dari relationship, bukan saya daftarkan sendiri.

Action: logika di luar CRUD

CRUD saja tidak cukup — panel admin biasanya punya tombol khusus: “publish sekarang”, “kirim ke email”, “reset password”. Di Filament hal ini disebut action, bisa ditaruh per baris tabel atau di header halaman:

Action::make('publish')
    ->requiresConfirmation()
    ->action(fn (Post $record) => $record->update(['is_published' => true]))

->requiresConfirmation() membuat dialog “yakin?” sebelum dieksekusi — jadi saya tidak perlu membangun modal konfirmasi sendiri. Action juga bisa membuka form (misal untuk input alasan), menjalankan job di queue, atau memicu notification sukses/gagal. Inilah bagian yang paling terasa “mahal” kalau dibuat manual: modal, state, loading, notifikasi — semuanya sudah jadi.

Kapan Filament layak dipakai (dan kapan tidak)

Saya sendiri menyimpulkan begini: kalau targetnya panel admin untuk tim internal atau dashboard CRUD untuk client, Filament hemat waktu sungguhan — saya bisa fokus ke logika bisnis, bukan ke tulang punggung tabel dan form. Tapi kalau tampilannya harus sangat custom (misal alur onboarding unik, animasi khas), deklarasi Filament bisa terasa membatasi dan saya tetap perlu turun ke Blade/Livewire manual.

Ini juga hubungannya dengan episode #26: Filament dibangun di atas Livewire, jadi semua yang saya pelajari soal lifecycle komponen dan state di sana justru membantu memahami kenapa Filament bisa interaktif tanpa saya menulis JavaScript. Untuk proyek kecil saya tetap pakai Blade biasa; begitu muncul kebutuhan admin yang berulang, saya baru ambil Filament. Di episode lanjutan (#29) saya akan mendalami sisi Filament yang lebih dalam: custom page, relationship manager, dan tema.

Filament juga tidak mengubah cara saya menulis aplikasi di luar admin: routing, Eloquent, queue, notification tetap Laravel biasa. Filament hanya menempel di lapisan tampilan-panel. Artinya, kalau suatu saat saya harus meninggalkan Filament, logika bisnis di model dan service tidak ikut terbuang. Rasa aman ini yang membuat saya berani memakainya di proyek nyata.

Sumber

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses