Tutorial Laravel 12 dan Filament 4 #9 Post Resource

Pelajari Laravel 12 dan Filament 4 dari dasar hingga tingkat lanjut dengan tutorial lengkap dan mudah dipahami. Laravel 12 adalah framework PHP yang powerful untuk membangun aplikasi web modern, sedangkan Filament 4 adalah framework admin panel berbasis Laravel yang memanfaatkan Livewire dan modern UI untuk membuat dashboard, manajemen data, hingga aplikasi kompleks dengan lebih cepat dan efisien.

✅ Telah dilihat 775 kali

Rating: 5.00 ⭐

... 20 August 2025, 14:59

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:

  • PostForm.php

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:

  • PostsTable.php

File ini dipakai untuk mengatur tampilan tabel di halaman daftar post. Misalnya:

  • Kolom titleuser.namecategory.namecreated_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.namecategory.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 UserPost, dan Categories. Semoga pembahasan ini dapat menambah wawasan dan bermanfaat bagi teman-teman semua.

Daftar eBook