分页
Laravel 的分页功能
简介
在其他的框架中,分页是令人非常烦恼的。 Laravel 的分页器为 查询构造器 和 Eloquent ORM 集成提供了方便,并提供基于数据库结果集的分页开箱即用。分页器生产的 HTML 兼容 Bootstrap CSS framework.
基本使用
对查询语句构造器进行分页
有几种方法可以对项目进行分页。最简单的是在 查询语句构造器 或 Eloquent 查询 中使用 paginate
方法。 paginate
方法会自动基于当前用户查看的当前页面来设置适当的限制和偏移。默认情况下,当前页面通过 HTTP 请求所带的 ?page
参数的值来检测。当然,这个值会被 Laravel 自动检测,并且自动插入到由分页器生产的链接中。
首先,让我们先来看看如何在查询上调用 paginate
方法。在这个例子中,传递给 paginate
方法的唯一参数是你希望在「每页」显示的数据数。在这种情况下,让我们指定希望每页显示 15
条数据:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\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]);
}
}
{note} 目前,使用
groupBy
语句的分页操作无法由 Laravel 有效执行。如果你需要在一个分页结果集中使用groupBy
,建议你查询数据库并手动创建分页器。
「简单分页」
如果你只需要在你的分页视图中显示简单的「上一页」和「下一页」的链接,你可以使用 simplePaginate
方法来执行更高效的查询。当你在渲染视图时不需要显示页码链接,这对于大数据集非常有用。
$users = DB::table('users')->simplePaginate(15);
对 Eloquent 模型进行分页
你也可以对 Eloquent 查询进行分页。在这个例子中,我们将对 User
模型进行分页并且每页显示 15
条数据。正如你看到的,语法几乎与基于查询语句构造器的分页相同:
$users = App\User::paginate(15);
当然,你可以在对查询设置了其他限制之后调用 paginate
方法,例如 where
子句:
$users = User::where('votes', '>', 100)->paginate(15);
你也可以在 Eloquent 模型进行分页使用 simplePaginate
方法:
$users = User::where('votes', '>', 100)->simplePaginate(15);
手动创建分页
有时候你可能希望手动创建一个分页实例,并传递其到项目数组中。你可以依据你的需求创建 Illuminate\Pagination\Paginator
或 Illuminate\Pagination\LengthAwarePaginator
实例。
Paginator
类不需要知道结果集中的数据项总数;然而,由于这个,该类没有用于检索最后一页索引的方法。LengthAwarePaginator
接收的参数几乎和 Paginator
一样;但是,它需要计算结果集中的数据项总数。
换一种说法,Paginator
对应于查询语句构造器和 Eloquent 的 simplePaginate
方法,而 LengthAwarePaginator
对应于 paginate
方法。
{note} 当手动创建分页器实例时,你应该手动「切割」传递给分页器的结果集。如果你不确定如何去做到这一点,查阅 PHP 的函数 array_slice 。
显示分页结果
当调用 paginate
方法的时候,你将会接收到一个 Illuminate\Pagination\LengthAwarePaginator
实例。而当你调用 simplePaginate
方法时,你将会接收到一个 Illuminate\Pagination\Paginator
实例。这些对象提供了一些描述结果集的方法。除了这些辅助方法,分页器是迭代器并且可以作为数组循环。因此,一旦检索到结果集,你可以使用 Blade 模板显示结果集并渲染页面链接:
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
links
方法将会渲染结果集中的其他页链接。这些链接中每一个都已经包含了 ?page
查询字符串变量。记住,links
方法生产的 HTML 兼容 Bootstrap CSS framework
自定义分页器的 URI
withPath
方法允许你在生成分页链接时自定义 URI 。例如,如果你想分页器生成的链接如 http://example.com/custom/url?page=N
,你应该传递 custom/url
到 withPath
方法:
Route::get('users', function () {
$users = App\User::paginate(15);
$users->withPath('custom/url');
//
});
附加参数到分页链接中
你可以使用 append
方法附加查询参数到分页链接中。例如,要附加 sort=votes
到每个分页链接,你应该这样调用 append
方法:
{{ $users->appends(['sort' => 'votes'])->links() }}
如果你希望附加「哈希片段」到分页器的链接中,你应该使用 fragment
方法。例如,要附加 #foo
到每个分页链接的末尾,应该这样调用 fragment
方法:
{{ $users->fragment('foo')->links() }}
将结果转换为 JSON
Laravel 分页器结果类实现了 Illuminate\Contracts\Support\Jsonable
接口契约并且提供 toJson
方法,所以它很容易将你的分页结果集转换为 Json。你也可以简单地通过从路由或者控制器动作返回分页实例并将其转换为 JSON :
Route::get('users', function () {
return App\User::paginate();
});
从分页器获取的 JSON 将包含元信息,如: total
, current_page
, last_page
等等。实际的结果对象将通过 JSON 数组中的 data
键来获取。 以下是一个从路由返回分页器实例创建的 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
}
]
}
自定义分页视图
在默认情况下,视图渲染显示的分页链接都兼容 Bootstrap CSS 框架。但是,如果你不使用 Bootstrap,你可以自定义你自己的视图去渲染这些链接。当在分页器实例中调用 links
方法,传递视图名称作为方法的第一参数:
{{ $paginator->links('view.name') }}
// 传递数据到视图中...
{{ $paginator->links('view.name', ['foo' => 'bar']) }}
然而,自定义分页视图最简单的方法是通过 vendor:publish
命令将它们导出到你的 resources/views/vendor
目录:
php artisan vendor:publish --tag=laravel-pagination
这个命令将视图放置在 resources/views/vendor/pagination
目录中。这个目录下的 default.blade.php
文件对应于默认分页视图。你可以简单地编辑这个文件以修改分页的 HTML 。
分页器实例方法
每个分页器实例通过以下方法提供额外的分页信息:
$results->count()
$results->currentPage()
$results->firstItem()
$results->hasMorePages()
$results->lastItem()
$results->lastPage() (当使用 simplePagination 时无效)
$results->nextPageUrl()
$results->perPage()
$results->previousPageUrl()
$results->total() (当使用 simplePagination 时无效)
$results->url($page)