Trong các framework khác, phân trang có thể rất khổ. Mặc định, trình phân trang của Laravel được tích hợp sẵn với query builder và Eloquent ORM, cung cấp một cách thuận tiện, dễ sử dụng để phân trang kết quả từ cơ sở dữ liệu. HTML được tạo ra bởi trình phân trang tương thích với Bootstrap CSS framework.
Có một số cách để phân trang. Đơn giản nhất là sử dụng phương thức paginate
trong một query builder hoặc một Eloquent query. Phương thức paginate
sẽ tự động đảm nhiệm việc set giới hạn và offset dựa trên trang hiện tại đang được người dùng xem. Mặc định, trang hiện tại sẽ được dò tìm giá trị của tham số page
trong HTTP request. Dĩ nhiên, giá trị này sẽ được tự động dò tìm bởi Laravel và cũng được tự động thêm vào sau các link sau quá trình phân trang.
Trong ví dụ này, chỉ có một tham số duy nhất được truyền vào phương thức paginate
đó là số lượng dữ liệu mà bạn muốn hiển thị "trên mỗi trang". Trong trường hợp này, hãy khai báo chúng ta muốn hiển thị 15
dữ liệu trên mỗi trang:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show all of the users for the application.
*
* @return Response
*/
public function index()
{
$users = DB::table('users')->paginate(15);
return view('user.index', ['users' => $users]);
}
}
{note} Hiện tại, các hành động phân trang mà có sử dụng câu lệnh
groupBy
thì không thể thực hiện được bởi Laravel. Nếu bạn cần sử dụnggroupBy
với một tập hợp kết quả đã được phân trang, bạn nên truy vấn vào cơ sở dữ liệu và tự tạo một trình phân trang riêng biệt dành cho bạn.
Nếu bạn chỉ cần hiển thị các link đơn giản ví dụ như "Next" và "Previous" trong view của bạn, bạn có thể sử dụng phương thức simplePaginate
để thực hiện query hiệu quả hơn. Điều này rất hữu ích cho các bộ dữ liệu lớn khi mà bạn không cần hiển thị toàn bộ các link khi hiển thị view của bạn:
$users = DB::table('users')->simplePaginate(15);
Bạn cũng có thể phân trang bằng các truy vấn Eloquent. Trong ví dụ này, chúng ta sẽ phân trang model User
với 15
dữ liệu trên mỗi trang. Như bạn có thể thấy, cú pháp này gần giống với phân trang bằng query builder:
$users = App\User::paginate(15);
Tất nhiên là, bạn có thể gọi paginate
sau khi set các điều kiện cho truy vấn, chẳng hạn như câu lệnh where
:
$users = User::where('votes', '>', 100)->paginate(15);
Bạn cũng có thể sử dụng phương thức simplePaginate
khi phân trang trên các model Eloquent:
$users = User::where('votes', '>', 100)->simplePaginate(15);
Thỉnh thoảng bạn có thể muốn tự tạo một instance phân trang riêng và truyền cho nó một mảng các dữ liệu. Bạn có thể làm như vậy bằng cách tạo một instance Illuminate\Pagination\Paginator
hoặc Illuminate\Pagination\LengthAwarePaginator
, tùy theo nhu cầu của bạn.
Class Paginator
không cần biết tổng số dữ liệu có trong tập kết quả; tuy nhiên, vì điều này, mà class cũng sẽ không có các phương thức để lấy ra các index của trang cuối cùng. LengthAwarePaginator
chấp nhận các tham số gần như tương tự Paginator
; tuy nhiên, nó yêu cầu tổng số dữ liệu có trong tập kết quả.
Nói cách khác, Paginator
tương ứng với phương thức simplePaginate
trong query builder và Eloquent, trong khi LengthAwarePaginator
tương ứng với phương thức paginate
.
{note} Khi tự tạo trình phân trang, bạn nên tự "phân chia" các phần tử có trong mảng kết quả mà bạn truyền nó cho trình phân trang. Nếu bạn không chắc chắn cách thực hiện việc này, hãy xem hàm array_slice.
Khi gọi phương thức paginate
, bạn sẽ nhận được một instance của Illuminate\Pagination\LengthAwarePaginator
. Khi gọi phương thức simplePaginate
, bạn sẽ nhận được một instance của Illuminate\Pagination\Paginator
. Các đối tượng này cung cấp một số phương thức mô tả cho tập kết quả. Ngoài các phương thức hỗ trợ này, các instances phân trang cũng là các vòng lặp và có thể được lặp như là một mảng. Vì vậy, khi bạn đã lấy được kết quả, thì bạn có thể hiển thị kết quả và hiển thị các link của các trang bằng Blade:
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
Phương thức links
sẽ hiển thị các link dẫn đến các trang còn lại có trong tập kết quả. Mỗi link này sẽ chứa một biến page
phù hợp. Hãy nhớ rằng, HTML được tạo bởi phương thức links
tương thích với Bootstrap CSS framework.
Phương thức withPath
cho phép bạn tùy biến URI cho trình phân trang khi tạo link. Ví dụ: nếu bạn muốn trình phân trang tạo ra các link như http://example.com/custom/url?page=N
, bạn hãy truyền custom/url
này cho phương thức withPath
:
Route::get('users', function () {
$users = App\User::paginate(15);
$users->withPath('custom/url');
//
});
Bạn có thể nối thêm các tham số vào các link phân trang bằng phương thức appends
. Ví dụ: để nối sort=votes
vào các link phân trang, bạn có thể thực hiện gọi đến phương thức appends
như sau:
{{ $users->appends(['sort' => 'votes'])->links() }}
Nếu bạn muốn nối thêm một "hash fragment" vào các URL của trình phân trang, bạn có thể sử dụng phương thức fragment
. Ví dụ: để nối #foo
vào cuối của mỗi link phân trang, hãy thực hiện gọi đến phương thức fragment
như sau:
{{ $users->fragment('foo')->links() }}
Các class kết quả phân trang của Laravel sẽ được implement một contract Interface Illuminate\Contracts\Support\Jsonable
và có sẵn phương thức toJson
, do đó rất dễ để chuyển đổi kết quả phân trang của bạn sang dạng JSON. Bạn cũng có thể chuyển đổi một instance phân trang thành JSON bằng cách trả nó về từ một action của một route hoặc một controller:
Route::get('users', function () {
return App\User::paginate();
});
JSON từ trình phân trang sẽ chứa thông tin meta như total
, current_page
, last_page
, và hơn thế nữa. Các đối tượng kết quả sẽ nằm trong key data
trong mảng JSON. Dưới đây là một ví dụ về JSON được tạo ra bằng cách trả về instance paginator từ một route:
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}
Mặc định, các view hiển thị các link phân trang tương thích với Bootstrap CSS framework. Tuy nhiên, nếu bạn không sử dụng Bootstrap, bạn có thể thoải mái tự định nghĩa các view của riêng bạn để hiển thị các link. Khi gọi phương thức links
trên một instance phân trang, hãy truyền tên view làm tham số đầu tiên cho phương thức:
{{ $paginator->links('view.name') }}
// Passing data to the view...
{{ $paginator->links('view.name', ['foo' => 'bar']) }}
Tuy nhiên, cách dễ nhất để tùy biến các view của phân trang là bằng cách export chúng vào thư mục resources/views/vendor
của bạn thông qua cách sử dụng lệnh vendor:publish
:
php artisan vendor:publish --tag=laravel-pagination
Lệnh này sẽ lưu các view vào trong thư mục resources/views/vendor/pagination
. File default.blade.php
trong thư mục này tương ứng với view mặc định của phân trang. Sửa file này sẽ sửa đổi HTML của phân trang.
Mỗi instance phân trang cung cấp thêm các thông tin phân trang thông qua các phương thức có sẵn sau:
$results->count()
$results->currentPage()
$results->firstItem()
$results->hasMorePages()
$results->lastItem()
$results->lastPage() (Not available when using simplePaginate)
$results->nextPageUrl()
$results->perPage()
$results->previousPageUrl()
$results->total() (Not available when using simplePaginate)
$results->url($page)
entry