Xây dựng Admin Panel với Filament v5
FilamentPHP là gì? Vì sao chúng ta nên dùng nó?
Thông thường, khi mình khởi tạo một dự án mới, sẽ tốn rất nhiều thời gian cho việc làm admin panel cũng như là làm các phần CRUD cho các bảng của mình, nhiều lúc sẽ có trường hợp mình lay hoay không biết làm sao cho đẹp, và thông thường thì kết quả nhìn cũng không được đẹp lắm dù tốn thời gian kinh khủng.
FilamentPHP (gọi tắt là Filament) ra đời để giải quyết vấn đề đó. Đây là một công cụ mã nguồn mở dựa trên TALL stack bao gồm Tailwindcss, Alpine.js, Laravel, Livewire, cho phép bạn tạo ra một trang quản trị đầy đủ chức năng — từ form, bảng, tìm kiếm, phân trang cho tới tích hợp các plugin biểu đồ, tương tác được — chỉ bằng cách viết file cấu hình PHP mà không cần phải đụng tới HTML hay CSS, đặc biệt là Javascript (trừ khi bạn muốn tuỳ chỉnh sâu hơn).
Filament v5 là phiên bản mới nhất hiện tại, mình nghĩ đây là thời điểm tốt nhất để học Filament nếu bạn chưa từng thử qua.
Filament rất phù hợp nếu bạn đang xây dựng các trang quản lý nội dung (CMS), hệ thống quản lý đơn hàng, dashboard nội bộ cho khách hàng, hoặc bất kỳ dự án nào cần một trang admin được làm nhanh nhưng vẫn chuyên nghiệp. Ngoài ra thì Filament cũng cho phép tạo các component tuỳ chỉnh để có thể tạo giao diện khác với những component có sẵn, nhưng sẽ cần 1 chút kiến thức về component và Livewire của Laravel.
Môi trường yêu cầu
PHP >= 8.2
Composer >= 2.x
Laravel >= 12.x
MySQL >= 8.x (hoặc MariaDB, PostgreSQL)
Node.js >= 20.x (cho Vite)
Trong bài này mình sẽ dùng phiên bản Laravel 12, các bạn có thể dùng bản mới nhất là Laravel 13 nếu có PHP >= 8.3
Bước 1: Cài đặt Laravel 12
Đầu tiên mình sẽ tạo một dự án Laravel mới bằng lệnh composer ở terminal (hoặc cmd ở máy tính Windows):
# Tạo project Laravel mới
composer create-project laravel/laravel filament-demo
# Mở project bằng VS Code
code filament-demo
Lưu ý: các bạn có thể sử dụng lệnh
laravel newđể cài đặt cũng được, nhưng lệnh composer sẽ cho mình bỏ qua tất cả các lựa chọn cài đặt Starter Kit và AI Boost của Laravel.
Tiếp theo cấu hình file .env để kết nối với database, chỉnh phần DB_CONNECTION thành mysql (hoặc mariadb/postgres). Nhập các phần tên database, username và password tương ứng:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=filament-demo
DB_USERNAME=root
DB_PASSWORD=
Tiếp theo ở terminal chạy các lệnh sau:
# Tạo các bảng database mặc định
php artisan migrate
# Cài đặt package npm
npm install
# Khởi động server Laravel và chạy npm run dev cùng lúc
composer run dev
Lưu ý:
composer run devsẽ chạy đồng thời cả PHP server lẫn Vite, tiết kiệm thời gian hơn so với chạy từng lệnh riêng.
Bước 2: Cài đặt Filament
Chúng ta dùng lệnh sau ở Terminal để tiến hành cài đặt Filament:
composer require filament/filament
Tiếp theo là cài đặt Admin Panel đầu tiên:
# Cài đặt Filament Panel (Admin Panel mặc định)
php artisan filament:install --panels
Lệnh này sẽ tạo file AdminPanelProvider trong thư mục app/Providers/Filament/AdminPanelProvider.php. Đây sẽ là nơi để cấu hình toàn bộ admin panel của bạn.
Lưu ý: Ở đây hệ thống sẽ hỏi bạn muốn panel id là gì, mặc định sẽ là
adminvới url truy cập là<host>/admin(ví dụhttp://localhost:8000/admin), bạn có thể tuỳ ý thay đổi, Filament sẽ tự thay đổi url và tên PanelProvider tương ứng theo.
Kế đến, chúng ta sẽ tạo user đầu tiên bằng Filament luôn:
php artisan make:filament-user
Hệ thống sẽ hỏi bạn các thông tin gồm username, email, password. Sau khi tạo User, truy cập vào Admin Panel bằng link:
http://localhost:8000/admin/login
Giờ đây sau khi truy cập vào giao diện admin, các bạn sẽ thấy một trang với giao diện khá đẹp, cùng với chức năng đăng xuất user, chức năng thay đổi Dark/Light mode đã có sẵn. Rất nhanh phải không!
Bước 3: Tạo CRUD đầu tiên bằng lệnh Filament Resource
Bước 3.1. Tạo model và migration cho Post
Đầu tiên, chúng ta cần tạo model và migration cho resource cần tạo, trong bài này mình sẽ dùng Post (Bài viết) để dễ hình dung:
# Tạo Model Post kèm Migration
php artisan make:model Post -m
Tuỳ chỉnh file migration trong thư mục database/migrations/…create_posts….php và sửa phần up:
// Tạo bảng "posts" trong database
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
Tiếp theo chạy lệnh migrate:
php artisan migrate
Các bạn vào app/Models/Post.php để cấu hình $fillable cho model (bắt buộc để Filament có thể thêm dữ liệu vào cột được):
class Post extends Model {
public $fillable = ['title', 'content'];
}
Bước 3.2. Tạo Filament Resource (Post CRUD)
Chạy lệnh sau trong terminal để tạo ra PostResource:
php artisan make:filament-resource Post
Ở đây có thể thêm tuỳ chọn
--generatesau Post để resource tự map với các cột trong database, hoặc thêm--simplenếu các bạn muốn create và edit là dạng popup (modal) thay vì 1 trang riêng.
Lệnh này sẽ tạo ra thư mục app/Filament/Resources/PostResource/ gồm:
app/Filament/Resources/
└── PostResource/
├── PostResource.php # Cấu hình chính của Post
├── Pages/
│ ├── ListPosts.php # Trang danh sách
│ ├── CreatePost.php # Trang tạo mới
│ └── EditPost.php # Trang chỉnh sửa
└── Schemas/
├── PostForm.php # Cấu hình Form
└── PostTable.php # Cấu hình Table
Các bạn có thể truy cập lại trang admin và sẽ nhìn thấy một phần mới là Post đã nằm trên sidebar.
Bước 4: Tuỳ chỉnh trong Filament
Mặc định khi lưu lại ở Create và Edit thì sẽ bị điều hướng về trang Edit. Để thay đổi, thêm hàm sau vào file CreatePost.php hoặc EditPost.php:
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
Hoặc cấu hình cho toàn bộ AdminPanel trong file AdminPanelProvider.php:
return $panel
->resourceCreatePageRedirect('index')
->resourceEditPageRedirect('index')
->...; // các dòng tiếp
Để tuỳ chỉnh ngôn ngữ cho table, thêm ->label() trong các phần TextColumn của file PostTable.php:
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('title')
->label('Tiêu đề')
->searchable() // Cho phép tìm kiếm
->sortable(), // Cho phép sắp xếp
TextColumn::make('content')
->label('Nội dung')
->toggleable(), // Ẩn/hiện được
TextColumn::make('created_at')
->label('Ngày tạo')
->dateTime('d/m/Y'), // Định dạng ngày
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(), // Nút xóa có confirm
]);
}
Tip: Ở phần
contenttrongPostForm, thay vì dùngTextArea, các bạn có thể dùng RichEditor để thấy một editor xịn mịn mà không cần phải xài thêm package nào.
Để thay đổi cách hiển thị tên Resource ở sidebar, chỉnh trong file PostResource.php:
protected static ?string $modelLabel = 'Bài viết';
protected static ?string $pluralModelLabel = 'Danh sách bài viết';
Để đổi toàn bộ các chỗ tiếng Anh mặc định sang tiếng Việt, thay đổi APP_LOCALE trong file .env:
APP_LOCALE=vi
Sau đó xoá config để Filament nhận đúng cấu hình:
php artisan config:clear
Bước 5: Tạo trường chọn mối quan hệ cho Form
Bước 5.1. Tạo model và migration cho Category
# Tạo Category model và file migration
php artisan make:model Category -m
# Tạo migration để thêm category_id vào bảng posts
php artisan make:migration alter_posts_add_category_id_table
Cấu hình các cột cho Category trong file migration:
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->unsignedInteger('id')->autoIncrement();
$table->string('name');
$table->timestamps();
});
}
Thêm khoá ngoại vào bảng posts:
public function up(): void
{
Schema::table('posts', function (Blueprint $table) {
$table->unsignedInteger('category_id')->nullable();
$table->foreign('category_id', 'fk_post_category')
->on('categories')
->references('id')
->cascadeOnUpdate()
->restrictOnDelete();
});
}
// Đảm bảo rollback được sạch
public function down(): void
{
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign('fk_post_category');
$table->dropColumn('category_id');
});
}
Chạy migrate:
php artisan migrate
Cấu hình $fillable và relationship trong model Post:
public $fillable = ['title', 'content', 'category_id'];
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
Bước 5.2. Tạo Category Resource
php artisan make:filament-resource Category --simple --generate
Các bạn có thể tuỳ chỉnh tương tự như với PostResource ở trên.
Bước 5.3. Tạo Select Category cho PostForm
Trong file PostForm.php, bổ sung thêm đoạn sau:
Select::make('category_id')
->label('Chuyên mục')
->relationship('category', 'name') // tên relation, tên cột hiển thị
->required()
->createOptionForm([ // Thêm chuyên mục mới trực tiếp
TextInput::make('name')
->label('Tên chuyên mục')
->required(),
]),
Bước 5.4. Hiển thị chuyên mục trong PostTable
TextColumn::make('category.name') // relation.tên_cột
->label('Chuyên mục')
->sortable()
->searchable(),
Lưu ý: Cú pháp
category.namelà cách Filament truy cập dữ liệu trong relationship liên quan. Filament đã tối ưu sẵn phần load model nên sẽ không xuất hiện tình trạng query N+1 khi dùng cách này.
Tổng kết
Qua bài này, mình đã hướng dẫn các bạn cách cài đặt Filament v5 trên Laravel 12, tạo ra các Resource CRUD, tuỳ chỉnh Table/Form, chuyển ngôn ngữ sang tiếng Việt, và xử lý quan hệ giữa các Model. Bằng cách sử dụng Filament, mình tin rằng việc xây dựng admin panel sẽ được rút ngắn đáng kể.
Nếu các bạn có câu hỏi hoặc thắc mắc gì, có thể để lại ở phần bình luận nhé!
Tài liệu tham khảo
- FilamentPHP Documentation — Tài liệu chính thức của FilamentPHP
- Laravel Documentation — Tài liệu Laravel phiên bản 12
- Bài viết gốc
- Hướng dẫn tạo CRUD siêu nhanh bằng Filament — Video gốc của bài viết này
All rights reserved