分页

本文档最新版为 7.x,旧版本可能放弃维护,推荐阅读最新版!

数据库: 分页

简介

在其它框架中,分页可能非常痛苦。Laravel 的分页器将 查询构造器Eloquent ORM 结合起来,提供了方便、易用的数据库结果集分页。通过分页器生成的 HTML 兼容 Bootstrap CSS 框架

基本用法

查询构造器分页

数据分页有几种方法。最简单的是使用 查询构造器Eloquent querypaginate 方法。paginate 方法根据用户浏览的当前页码,自动设置恰当的偏移量offset和限制数limit。默认情况下,HTTP 请求中的 page 查询参数值被当作当前页的页码。Lavarel 自动侦测该值,并自动将其插入到分页器生成的链接中。

在下面的例子中,传递给 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]);
    }
}

注意:目前,Lavarel 无法高效地执行使用了 groupBy 语句的分页操作。如果你需要使用对使用了 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\PaginatorIlluminate\Pagination\LengthAwarePaginator 实例来实现,这有赖于你的需要。.

Paginator 类不需要知道结果集的总数;但是,这样一来,这个类就没办法获知最后一页的索引。 LengthAwarePaginator 接受和 Paginator 几乎相同的参数;不过,它会计算结果集的总数。

换句话说, Paginator 相当于 查询构造器 或 Eloquent 的 simplePaginate 方法,而 LengthAwarePaginator 相当于 paginate 方法。

注意:在手动创建分页实例时,需要人为 “切割” 传递给分页实例的结果数组。如果你对此没有把握,请参考 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 兼容 Bootstrap CSS 框架

自定义分页器 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');

    //
});

附加参数到分页链接

可以使用 appends 方法,向分页链接中添加查询参数。例如,要在每页链接中添加 sort=votes ,只需要这样调用 appends:

{{ $users->appends(['sort' => 'votes'])->links() }}

如果想要向分页器 URL 添加 “哈希片段”,可以使用 fragment 方法。例如,要在每页链接中添加 #foo ,只要这样调用 fragment 方法:

{{ $users->fragment('foo')->links() }}

调整分页链接窗口

你能够控制在分页器的 “窗口” 的每一侧显示多少个附加链接。默认情况下,主分页链接的每侧显示三个链接。可以使用 onEachSide 方法改变这个数值:

{{ $users->onEachSide(5)->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,
   "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":[
        {
            // 结果集对象
        },
        {
            // 结果集对象
        }
   ]
}

自定义分页视图

默认情况下,渲染视图以显示分页链接与 Bootstrap CSS 框架兼容。如果你不使用 Bootstrap,可以随心所欲地定制自己的视图来渲染这些链接。在调用分页器实例的 links 方法时,将视图名称作为传递给它的第一个参数:

{{ $paginator->links('view.name') }}

// Passing data to the view...
{{ $paginator->links('view.name', ['foo' => 'bar']) }}

自定义分页视图的最简方法是使用 vendor:publish 命令将它们输出到 resources/views/vendor 文件夹:

   php artisan vendor:publish --tag=laravel-pagination

此命令将在 resources/views/vendor/pagination 文件夹放置这些视图。内置在该文件夹下的 bootstrap-4.blade.php 文件提供了默认的分页视图。可以编辑此文件以修改分页 HTML。

如果想要定义不同的文件作为默认分页视图,需要在 AppServiceProvider 中使用分页器的 defaultViewdefaultSimpleView 方法:

use Illuminate\Pagination\Paginator;

public function boot()
{
    Paginator::defaultView('view-name');

    Paginator::defaultSimpleView('view-name');
}

分页器实例方法

每个分页器实例提供了如下方法获取附加的分页信息::

方法 描述
$results->count() 获取当前页数据数量。
$results->currentPage() 获取当前页页码。
$results->firstItem() 获取结果集中第一条数据的结果编号。
$results->getOptions() 获取分页器选项。
$results->getUrlRange($start, $end) 创建分页 URL 范围。
$results->hasMorePages() 是否有多页。
$results->lastItem() 获取结果集中最后一条数据的结果编号。
$results->lastPage() 获取最后一页的页码(在 simplePaginate 中无效)。
$results->nextPageUrl() 获取下一页的 URL 。
$results->onFirstPage() 当前页是否为第一页。
$results->perPage() 每页的数据条数。
$results->previousPageUrl() 获取前一页的 URL。
$results->total() 数据总数(在 simplePaginate 无效)。
$results->url($page) 获取指定页的 URL。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
贡献者:6