简介 在其他框架中,分页可能是非常痛苦。Laravel 的分页器将 查询构造器 和 Eloquent ORM 结合起来,提供了方便、易用的数据库结果集分页。通过分页器生成的 HTML 兼容 Bootstrap CSS 框架。 基本用法 查询构造器分页 数据分页有多种方法。最简单的是使用 查询构造器 或 Eloquent query 的 paginate 方法。paginate 方法根据用户浏览的当前页码,自动设置恰当的偏移量 offset 和限制数 limit。默认情况下,HTTP 请求中的 page 查询参数值被当作当前页的页码。 Laravel 会自动检测该值,并自动将其插入到分页器生成的链接中。 在下面的例子中,传递给 paginate 方法的唯一参数是你想要在每页显示的记录数。在此例中,我们指定要在每页显示 15 条数据: ``` <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\DB; class UserController extends Controller { /** * 显示该应用程序的所有用户。 * * @return Response */ public function index() { $users = DB::table('users')->paginate(15); return view('user.index', ['users' => $users]); } } ``` 注意:目前,Laravel 无法高效地执行使用 groupBy 语句的分页操作。如果你需要对使用了 groupBy 的结果集分页,建议你手动查询数据库并创建分页。 "简单分页" 如果你只需要在分页视图中简单地显示「下一页」和「上一页」的链接,你可以使用 simplePaginate 方法来执行更高效地查询。这在数据量很大且不需要在渲染视图时显示每页的页码时非常有用: ``` $users = DB::table('users')->simplePaginate(15); ``` Eloquent 分页 你还可以对 Eloquent 查询结果进行分页。在下面的例子中,我们将 User 模型按每页 15 条分页。如你所见,其语法与查询构造器分页基本相同: ``` $users = App\Models\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 方法。 注意:在手动创建分页实例时,需要人为「slice」传递给分页实例的结果数组。如果你对此没有把握,请参考 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 URL 变量。记住, links 方法生成的 HTML 兼容 Tailwind CSS 框架。 自定义分页器 URI withPath 方法允许你在生成分页链接时自定义 URI。例如,如果你想生成像 http://example.com/custom/url?page=N 的分页链接,你应该传递 custom/url 参数给 withPath 方法: ``` Route::get('users', function () { $users = App\Models\User::paginate(15); $users->withPath('custom/url'); // }); ``` 附加参数到分页链接 你可以使用 appends 方法向分页链接中添加查询参数。例如,要在每个分页链接中添加 sort=votes ,你应该这样调用 appends: ``` {{ $users->appends(['sort' => 'votes'])->links() }} ``` 如果你想要把所有的查询参数值添加到分页链接,可以使用 withQueryString 方法: ``` {{ $users->withQueryString()->links() }} ``` 如果你希望向分页器的 URL 添加「哈希片段」,你可以使用 fragment 方法。要在每页链接中添加 #foo ,应该这样调用 fragment 方法: ``` {{ $users->fragment('foo')->links() }} ``` 调整分页链接窗口 你可以控制在分页器 URL「窗口」的每一侧显示多少个附加链接。默认情况下,主分页链接的每侧显示三个链接。但是,你可以使用 onEachSide 方法来控制这个值: ``` {{ $users->onEachSide(5)->links() }} ``` 将结果转换为 JSON Laravel 分页器类实现了 Illuminate\Contracts\Support\Jsonable 接口契约,提供了 toJson 方法,所以可以方便的将分页结果转换为 JSON 。你也可以通过来自路由或控制器的操作返回分页实例来将其转换为 JSON: ``` Route::get('users', function () { return App\Models\User::paginate(); }); ``` 来自分页器的 JSON 包括诸如 total,current_page,last_page 等元数据信息。实际结果对象将通过 JSON 数组的 data 键提供。以下是通过自路由中分页器实例的方式创建 JSON 的例子: ``` { "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 } ] } ``` 自定义分页视图 默认情况下,渲染视图来显示分页链接是与 Tailwind CSS 框架兼容的。然而,如果你不想使用 Tailwind,你可以自由的选择你自己定制的视图来渲染这些链接。在调用分页器实例的 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 目录中放置这些视图。内置在该目录下的 tailwind.blade.php 文件提供了默认的分页视图。你可以编辑这个文件来修改分页的 HTML。 如果你想要定义不同的文件作为默认的分页视图,你需要在 AppServiceProvider 中使用分页器的 defaultView 和 defaultSimpleView 方法: ``` use Illuminate\Pagination\Paginator; public function boot() { Paginator::defaultView('view-name'); Paginator::defaultSimpleView('view-name'); } ``` 使用 Bootstrap Laravel 包含使用 Bootstrap CSS 构建的分页视图。 要使用这些视图而不是默认的 Tailwind 视图,可以在 AppServiceProvider 中调用分页器的 useBootstrap 方法 : ``` use Illuminate\Pagination\Paginator; public function boot() { Paginator::useBootstrap(); } ``` 分页器实例方法 每个分页器实例提供了如下方法来获取附加的分页信息: |方法 |描述| |----|-----| |$paginator->count() |获取当前页数据的数量。| |$paginator->currentPage()| 获取当前页页码。| |$paginator->firstItem() |获取结果集中第一条数据的结果编号。| |$paginator->getOptions() |获取分页器选项。| |$paginator->getUrlRange($start, $end) |创建分页 URL 的范围。| |$paginator->hasPages() |是否有多页。| |$paginator->hasMorePages() |是否有更多页。| |$paginator->items() |获取当前页的所有项。| |$paginator->lastItem() |获取结果集中最后一条数据的结果编号。| |$paginator->lastPage()| 获取最后一页的页码。(在 simplePaginate 无效)。| |$paginator->nextPageUrl()| 获取下一页的 URL。| |$paginator->onFirstPage()| 当前页是否为第一页。| |$paginator->perPage()| 每页的数据条数。| |$paginator->previousPageUrl() |获取前一页的 URL。| |$paginator->total() |数据总数(在 simplePaginate 无效)。| |$paginator->url($page) |获取指定页的 URL。| |$paginator->getPageName() |获取分页的查询字符串变量。| |$paginator->setPageName($name) |设置分页的查询字符串变量。|