PHP và MySQL Bài 39. Hướng dẫn tôi cách làm tính năng Phân trang (Pagination) cực kỳ ngắn gọn bằng Laravel Eloquent và Blade.
Trong PHP thuần, để làm được tính năng phân trang, bạn phải thực hiện một loạt các bước tính toán thủ công đau đầu: đếm tổng số bản ghi, chia cho số bài trên 1 trang để tìm ra tổng số trang, bắt tham số ?page= trên URL, rồi nối chuỗi LIMIT offset, limit vào câu SQL.
Nhưng với Laravel, tất cả những logic phức tạp đó được gói gọn trong đúng 1 từ.
1. Sửa Controller: Thay all() bằng paginate()
Hãy mở file app/Http/Controllers/HomeController.php và tìm đến dòng code lấy dữ liệu của Bài 37.
- Cách cũ (Gây sập nguồn nếu có hàng triệu bài):
$posts = Post::all(); - Cách mới (Phân trang với Laravel):
// Chia nhỏ dữ liệu, mỗi trang chỉ lấy đúng 10 bài viết $posts = Post::paginate(10);
Chỉ với hàm paginate(10), Laravel tự động làm mọi thứ ngầm bên dưới: nó tự đếm tổng số bài, tự bắt tham số ?page= trên URL từ người dùng, và tự sinh ra các câu lệnh SQL LIMIT tương ứng một cách hoàn hảo.
2. Cập nhật View: Hiển thị thanh điều hướng (Links)
Bây giờ, dữ liệu truyền sang View đã được cắt nhỏ thành từng trang (10 bài/trang). Việc tiếp theo là hiển thị thanh điều hướng (các nút 1, 2, 3, Next, Previous) ra màn hình.
Mở file resources/views/home.blade.php, kéo xuống dưới cùng của danh sách bài viết (bên dưới thẻ đóng @endforelse), và chèn thêm đoạn code sau:
<div class="danh-sach">
@forelse ($posts as $post)
<!-- Hiển thị bài viết (Giữ nguyên như Bài 36) -->
<div style="border: 1px solid #ccc; padding: 10px; margin-bottom: 10px;">
<h2>{{ $post->title }}</h2>
<!-- Giới hạn text dài, chỉ lấy 150 ký tự -->
<p>{{ Str::limit($post->content, 150) }}</p>
</div>
@empty
<p>Dữ liệu đang trống!</p>
@endforelse
</div>
<!-- Phép thuật hiển thị thanh phân trang nằm ở dòng này -->
<div style="margin-top: 20px;">
{{ $posts->links() }}
</div>
Hàm links() sẽ tự động sinh ra toàn bộ mã HTML phức tạp cho thanh phân trang.
3. Khắc phục lỗi giao diện phân trang khổng lồ (CSS Framework)
Nếu bạn ra trình duyệt F5 lại lúc này, bạn sẽ thấy 10 bài viết được hiển thị, nhưng thanh phân trang ở dưới cùng có thể bị vỡ giao diện (các icon mũi tên to đùng hoặc các nút bấm nằm lộn xộn).
- Nguyên nhân: Mặc định ở các phiên bản mới nhất, Laravel sử dụng CSS Framework là Tailwind CSS để thiết kế thanh phân trang. Nếu dự án của bạn chưa cài đặt Tailwind, HTML sinh ra sẽ không có CSS để định dạng.
- Cách giải quyết (Chuyển về Bootstrap mặc định): Đa số Backend Developer thường quen dùng Bootstrap để làm giao diện nhanh. Laravel cho phép bạn đổi giao diện phân trang về chuẩn Bootstrap chỉ với 1 thao tác cấu hình.
Mở file app/Providers/AppServiceProvider.php và thêm 2 dòng code vào hàm boot():
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator; // BẮT BUỘC: Gọi class Paginator vào
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// Ép Laravel sử dụng giao diện phân trang của Bootstrap 5
Paginator::useBootstrapFive();
// Hoặc nếu bạn thích dùng bản cũ: Paginator::useBootstrapFour();
}
}
Để thanh phân trang thực sự hiển thị đúng chuẩn, bạn nhớ nhúng link CSS của Bootstrap vào thẻ <head> trong file home.blade.php:
<head>
<title>Trang Chủ</title>
<!-- Nhúng CSS của Bootstrap qua CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
Ra trình duyệt và tải lại trang, một thanh phân trang vô cùng chuẩn mực và chuyên nghiệp đã xuất hiện. Thử click vào trang 2, trang 3, hoặc sửa URL thành ?page=5 để chiêm ngưỡng tốc độ xử lý thực sự của Laravel.
Tổng kết Bài 39
Từ việc loay hoay với những câu truy vấn phức tạp của PHP thuần, Laravel đã rút gọn trải nghiệm làm Backend xuống mức tối giản và thanh lịch nhất. Tính năng phân trang vốn là điểm dễ gây lỗi cú pháp SQL nhất với người mới học giờ chỉ còn lại 2 thao tác: paginate(10) và links().
Bạn đã nắm vững luồng lấy dữ liệu (Read) từ Database hiển thị ra màn hình. Vậy làm thế nào để hứng dữ liệu do người dùng nhập từ Form, kiểm tra tính hợp lệ và lưu ngược lại vào Database một cách an toàn?
All Rights Reserved