Post Resource
Untuk membuat resource Post, jalankan perintah:
php artisan make:filament-resource Post --generate
Akan muncul beberapa pertanyaan:
The "title attribute" is used to label each record in the UI.
You can leave this blank if records do not have a title.
What is the title attribute for this model?
❯ title
Would you like to generate a read-only view page for the resource? (yes/no) [no]
❯ yes
- What is the title attribute for this model? → Masukkan
title, karena field ini yang paling representatif untuk Post.
- Would you like to generate a read-only view page for the resource? → Pilih yes, agar kita bisa melihat detail setiap post.
Maka di dalam folder app/Filament/Resources/ akan muncul folder Post.
1. PostResource.php
- File utama resource.
- Di sini ditentukan model yang dipakai (
Post::class).
- Menghubungkan form schema (untuk create/edit post) dan table schema (untuk daftar post).
- Bisa dibilang ini adalah “pintu masuk” resource Post.
2. Pages/
Di folder Pages ada 4 file:
CreatePost.php → Halaman membuat post baru.
EditPost.php → Halaman mengedit post yang ada.
ListPosts.php → Halaman menampilkan daftar semua post.
ViewPost.php → Halaman menampilkan detail post (karena tadi kita pilih yes untuk generate view).
Keempat file ini sudah otomatis terhubung dengan PostResource.
3. Schemas/
Di folder ini ada:
File ini mengatur field di form create/edit post. Misalnya:
TextInput::make('title') → untuk judul post
Textarea::make('content') → untuk konten
FileUpload::make('image') → untuk upload gambar
Select::make('user_id') → untuk memilih user yang membuat post
Select::make('category_id') → untuk memilih kategori
Dengan pemisahan ini, form schema jadi lebih rapi dan modular.
4. Tables/
Di folder ini ada:
File ini dipakai untuk mengatur tampilan tabel di halaman daftar post. Misalnya:
- Kolom
title, user.name, category.name, created_at
- Sorting dan searching berdasarkan judul
- Filter berdasarkan kategori
- Action edit, view, dan delete
Konfigurasi PostForm
Silakan teman-teman buka file PostForm.php yang terletak didalam folder App\Filament\Resources\Posts\Schemas kemudian ubah menjadi seperti berikut ini:
<?php
namespace App\Filament\Resources\Posts\Schemas;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
class PostForm
{
public static function configure(Schema $schema): Schema
{
return $schema->schema([
TextInput::make('title')
->label('Title')
->required()
->maxLength(255),
FileUpload::make('image')
->image()
->directory('posts')
->disk('public')
->visibility('public'),
RichEditor::make('content')
->label('Content')
->required()
->columnSpanFull(),
Select::make('user_id')
->label('Author')
->relationship('user', 'name')
->searchable()
->required(),
Select::make('category_id')
->label('Category')
->relationship('category', 'name')
->searchable()
->required(),
]);
}
}
Berikut beberapa konfigurasi yang kita tambahkan:
Field: Title
TextInput::make('title')
->label('Title')
->required()
->maxLength(255),
TextInput::make('title'): mengikat input ke kolom title pada model Post.
label('Title'): label di UI.
required(): menambahkan validasi wajib diisi.
maxLength(255): validasi panjang maksimal 255 karakter (umum untuk kolom VARCHAR(255) di DB).
Field: Image
FileUpload::make('image')
->image()
->directory('posts')
->disk('public')
->visibility('public'),
FileUpload::make('image'): mengikat upload ke kolom image (path file akan disimpan di DB).
image(): membatasi hanya file gambar + menampilkan preview.
directory('posts'): file disimpan dalam folder posts/ pada disk yang dipilih.
disk('public'): gunakan disk public (biasanya storage/app/public). Pastikan sudah php artisan storage:link.
visibility('public'): menetapkan visibilitas publik (berguna untuk S3/FTP; di local akan atur permission file).
Hasil akhirnya: file tersimpan di storage/app/public/posts/... dan bisa diakses publik via public/storage/posts/....
Field: Content
RichEditor::make('content')
->label('Content')
->required()
->columnSpanFull(),
RichEditor::make('content'): editor WYSIWYG untuk isi artikel.
required(): wajib diisi.
columnSpanFull(): membentang penuh 1 baris grid form (nyaman untuk area teks panjang).
Field: Author (Relasi User)
Select::make('user_id')
->label('Author')
->relationship('user', 'name')
->searchable()
->required(),
Select::make('user_id'): select yang menulis nilai ke kolom user_id.
relationship('user', 'name'): ambil opsi dari relasi user() pada model Post, tampilkan kolom name sebagai label. Filament otomatis:
- load data dari model terkait,
- isi
user_id saat simpan.
searchable(): ada kotak pencarian (berguna kalau user banyak).
required(): wajib pilih author.
relasi public function user() { return $this->belongsTo(User::class); } didalam model Post.
Field: Category (Relasi Category)
Select::make('category_id')
->label('Category')
->relationship('category', 'name')
->searchable()
->required(),
- Mirip dengan
user_id, tapi untuk relasi kategori:
relationship('category', 'name'): ambil opsi dari relasi category() dan tampilkan name.
- searchable + required: UX enak + wajib pilih.
relasi public function category() { return $this->belongsTo(Category::class); } didalam model Post.
Konfigurasi PostInfolist
Silakan teman-teman buka file PostInfolist.php yang terletak didalam folder App\Filament\Resources\Posts\Schemas kemudian ubah menjadi seperti berikut ini:
<?php
namespace App\Filament\Resources\Posts\Schemas;
use Filament\Infolists\Components\ImageEntry;
use Filament\Schemas\Components\Section;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Schema;
class PostInfolist
{
public static function configure(Schema $schema): Schema
{
return $schema->components([
Section::make('Post Information')
->columns(2)
->schema([
TextEntry::make('title')
->label('Title')
->weight('bold'),
ImageEntry::make('image')
->label('Thumbnail')
->disk('public')
->visibility('public')
->square(),
]),
Section::make('Relations')
->columns(2)
->schema([
TextEntry::make('user.name')
->label('Author'),
TextEntry::make('category.name')
->label('Category'),
]),
Section::make('Timestamps')
->columns(2)
->schema([
TextEntry::make('created_at')
->label('Created At')
->dateTime('d M Y H:i'),
TextEntry::make('updated_at')
->label('Updated At')
->dateTime('d M Y H:i'),
]),
]);
}
}
Berikut beberapa konfigurasi yang kita tambahkan:
Section: Post Information
Section::make('Post Information')
->columns(2)
->schema([
TextEntry::make('title')->label('Title')->weight('bold'),
ImageEntry::make('image')->label('Thumbnail')->disk('public')->visibility('public')->square(),
]),
- Menampilkan judul post (
title) dengan teks tebal.
- Menampilkan gambar (
image) dari disk public/posts.
- Dibuat 2 kolom agar lebih rapi: judul di kiri, gambar di kanan.
Section: Relations
Section::make('Relations')
->columns(2)
->schema([
TextEntry::make('user.name')->label('Author'),
TextEntry::make('category.name')->label('Category'),
]),
- Menampilkan author dari relasi
user (user.name).
- Menampilkan kategori dari relasi
category (category.name).
- Ditata 2 kolom: kiri author, kanan kategori.
- Tidak lagi menampilkan angka
user_id / category_id.
Section: Timestamps
Section::make('Timestamps')
->columns(2)
->schema([
TextEntry::make('created_at')->label('Created At')->dateTime('d M Y H:i'),
TextEntry::make('updated_at')->label('Updated At')->dateTime('d M Y H:i'),
]),
- Menampilkan waktu dibuat (
created_at) dan diperbarui (updated_at).
- Format ditampilkan sebagai
dd MMM YYYY HH:mm (misal: 27 Aug 2025 14:32).
- Ditata dalam 2 kolom berdampingan.
Konfigurasi PostsTable
Silakan teman-teman buka file PostsTable.php yang terletak didalam folder App\Filament\Resources\Posts\Tables kemudian ubah menjadi seperti berikut ini:
<?php
namespace App\Filament\Resources\Posts\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class PostsTable
{
public static function configure(Table $table): Table
{
return $table
->columns([
TextColumn::make('title')
->label('Title')
->searchable()
->sortable()
->limit(50),
ImageColumn::make('image')
->label('Thumbnail')
->disk('public')
->width(40),
TextColumn::make('user.name')
->label('Author')
->sortable()
->searchable(),
TextColumn::make('category.name')
->label('Category')
->sortable()
->searchable(),
TextColumn::make('created_at')
->label('Created At')
->dateTime('d M Y H:i')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')
->label('Updated At')
->dateTime('d M Y H:i')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([])
->recordActions([
ViewAction::make(),
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
}
Berikut beberapa konfigurasi yang kita tambahkan:
Kolom title
TextColumn::make('title')
->label('Title')
->searchable()
->sortable()
->limit(50),
- Bisa dicari (searchable), diurutkan (sortable), dan teks panjang dipotong jadi max 50 karakter.
Kolom image
ImageColumn::make('image')
->label('Thumbnail')
->disk('public')
->width(40),
- Tampilkan gambar dari
disk('public').
- Ukuran kecil (40x40) biar tabel tetap ringkas.
Kolom relasi user & category
TextColumn::make('user.name')
->label('Author')
->sortable()
->searchable(),
TextColumn::make('category.name')
->label('Category')
->sortable()
->searchable(),
- Tidak lagi pakai angka
user_id / category_id, tapi langsung nama (user.name, category.name).
- Bisa dicari (searchable) & diurutkan (sortable).
Kolom timestamps
TextColumn::make('created_at')
->label('Created At')
->dateTime('d M Y H:i')
->sortable()
->toggleable(isToggledHiddenByDefault: true),
- Format
27 Aug 2025 14:30.
- Toggleable (bisa disembunyikan oleh user).
Uji Coba
Silakan teman-teman masuk kedalam halaman posts dengan cara klik menu post didalam sidebar kiri, atau bisa juga langsung mengakses url berikut ini:
http://127.0.0.1:8000/admin/posts

Index Posts

Create Post

View Post

Edit Post

Table PostList

Multiple Delete Post


Pada akhir materi ini, kita berhasil membangun sebuah aplikasi sederhana menggunakan Laravel 12 dan Filament 4, dengan implementasi relasi antara User, Post, dan Categories. Semoga pembahasan ini dapat menambah wawasan dan bermanfaat bagi teman-teman semua.