在其他框架中,分頁是件非常痛苦的事,Laravel 則使其變得輕而易舉。Laravel 能夠基于當前頁智能生成一定范圍的鏈接,且生成的 HTML 兼容 Bootstrap CSS 框架。
有多種方式實現(xiàn)分頁,最簡單的方式就是使用查詢構(gòu)建器或 Eloquent 模型的 paginate
方法。該方法基于當前用戶查看頁自動設置合適的偏移(offset)和限制(limit)。默認情況下,當前頁通過 HTTP 請求查詢字符串參數(shù)?page
的值判斷。當然,該值由 Laravel 自動檢測,然后自動插入分頁器生成的鏈接中。
讓我們先來看看如何在查詢上調(diào)用 paginate
方法。在本例中,傳遞給 paginate
的唯一參數(shù)就是你每頁想要顯示的數(shù)目,這里我們指定每頁顯示 15
個:
<?php
namespace App\Http\Controllers;
use DB;
use App\Http\Controllers\Controller;
class UserController extends Controller{
/**
* 顯示應用中的所有用戶
*
* @return Response
*/
public function index()
{
$users = DB::table('users')->paginate(15);
return view('user.index', ['users' => $users]);
}
}
注意:目前,使用 groupBy
的分頁操作不能被 Laravel 有效執(zhí)行,如果你需要在分頁結(jié)果中使用 groupBy
,推薦你手動查詢數(shù)據(jù)庫然后創(chuàng)建分頁器。
如果你只需要在分頁視圖中簡單的顯示“下一個”和“上一個”鏈接,可以使用 simplePaginate
方法來執(zhí)行該查詢。在渲染包含大數(shù)據(jù)集的視圖且不需要顯示每個頁碼時非常有用:
$users = DB::table('users')->simplePaginate(15);
你還可以對 Eloquent 查詢結(jié)果進行分頁,在本例中,我們對 User
模型進行分頁,每頁顯示15
條記錄。正如你所看到的,該語法和基于查詢構(gòu)建器的分頁差不多:
$users = App\User::paginate(15);
當然,你可以在設置其它約束調(diào)價之后調(diào)用 paginate
,比如 where
子句:
$users = User::where('votes', '>', 100)->paginate(15);
你也可以使用 simplePaginate
方法:
$users = User::where('votes', '>', 100)->simplePaginate(15);
有時候你可能想要通過傳遞數(shù)組數(shù)據(jù)來手動創(chuàng)建分頁實例,你可以基于自己的需求通過創(chuàng)建 Illuminate\Pagination\Paginator 或 Illuminate\Pagination\LengthAwarePaginator
實例來實現(xiàn)。
Paginator
類不需要知道結(jié)果集中數(shù)據(jù)項的總數(shù);然而,正因如此,該類也沒有提供獲取最后一頁索引的方法。
LengthAwarePaginator
接收參數(shù)和 Paginator
幾乎一樣,只是,它要求傳入結(jié)果集的總數(shù)。
換句話說,Paginator
對應 simplePaginate
方法,而 LengthAwarePaginator
對應 paginate
方法。
當手動創(chuàng)建分頁器實例的時候,應該手動對傳遞到分頁器的結(jié)果集進行“切片”,如果你不確定怎么做,查看 PHP 函數(shù) array_slice。
當你調(diào)用查詢構(gòu)建器或 Eloquent 查詢上的 paginate
或 simplePaginate
方法時,你將會獲取一個分頁器實例。當調(diào)用 paginate
方法時,你將獲取 Illuminate\Pagination\LengthAwarePaginator
,而調(diào)用方法 simplePaginate
時,將會獲取 Illuminate\Pagination\Paginator
實例。這些對象提供相關(guān)方法描述這些結(jié)果集,除了這些幫助函數(shù)外,分頁器實例本身就是迭代器,可以像數(shù)組一樣對其進行循環(huán)調(diào)用。
所以,獲取到結(jié)果后,可以按如下方式使用 Blade 顯示這些結(jié)果并渲染頁面鏈接:
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{!! $users->render() !!}
render
方法將會將結(jié)果集中的其它頁面鏈接渲染出來。每個鏈接已經(jīng)包含了?page
查詢字符串變量。記住,render
方法生成的 HTML 兼容 Bootstrap CSS 框架。
注意:我們從 Blade 模板調(diào)用 render
方法時,確保使用{!! !!}
語法以便 HTML 鏈接不被過濾。
setPath
方法允許你生成分頁鏈接時自定義分頁器使用的 URI,例如,如果你想要分頁器生成形如 http://example.com/custom/url?page=N
的鏈接,應該傳遞 custom/url
到 setPath
方法:
Route::get('users', function () {
$users = App\User::paginate(15);
$users->setPath('custom/url');
//
});
你可以使用 appends
方法添加查詢參數(shù)到分頁鏈接查詢字符串。例如,要添加&sort=votes
到每個分頁鏈接,應該像如下方式調(diào)用appends
:
{!! $users->appends(['sort' => 'votes'])->render() !!}
如果你想要添加”哈希片段”到分頁鏈接,可以使用fragment
方法。例如,要添加#foo
到每個分頁鏈接的末尾,像這樣調(diào)用 fragment
方法:
{!! $users->fragment('foo')->render() !!}
你還可以通過如下分頁器實例上的方法訪問更多分頁信息:
$results->count()
$results->currentPage()
$results->hasMorePages()
$results->lastPage() (使用 simplePaginate 時無效)
$results->nextPageUrl()
$results->perPage()
$results->total() (使用 simplePaginate 時無效)
$results->url($page)
Laravel 分頁器結(jié)果類實現(xiàn)了 Illuminate\Contracts\Support\JsonableInterface
契約并實現(xiàn) toJson
方法,所以將分頁結(jié)果轉(zhuǎn)化為 JSON 非常簡單。
你還可以簡單通過從路由或控制器動作返回分頁器實例將轉(zhuǎn)其化為 JSON:
Route::get('users', function () {
return App\User::paginate();
});
從分頁器轉(zhuǎn)化來的 JSON 包含了元信息如 total
, current_page
,last_page
等等,實際的結(jié)果對象數(shù)據(jù)可以通過該 JSON 數(shù)組中的 data
鍵訪問。下面是一個通過從路由返回的分頁器實例創(chuàng)建的 JSON 例子:
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"from": 1,
"to": 15,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}