替换 Laravel 分页组件默认生成的模板

本人博客原文地址: https://www.insp.top/article/php-knowledge... 转载请注明原文地址!

在使用 Laravel 分页功能时,需要配合使用前端框架 Bootstrap 的分页组件,这两者结合甚为紧密。可是由于我的博客更换为 AmazeUI,而 AmazeUI 分页组件使用的 CSS 类选择器是 .am-pagination 而不是 Bootstrap 的 .pagination

那么如何在不修改框架代码的前提下替换默认的 Laravel Pagination 生成的 html 模板呢?本文将通过利用 Laravel Service Provider (服务提供者)实现该需求。通过了解本文的内容大家也可以实现更多的分页样式。

关于 Laravel 的 Pagination (分页)组件

Laravel 的分页组件其实从一开始就考虑到这个需求,但是文档上根本就没有写如何操作,导致很多人误解 Laravel 的分页组件并不适用于复杂场景。其实通过查阅 API 文档或者直接查看 Illuminate\Pagination\Paginator 类,可以发现 laravel 的分页组件是十分灵活的。查看该类的 render 方法,可以注意到实际生成分页 html 模板的是一个实现 Illuminate\Contracts\Pagination\Presenter 接口的实例,我们只需要实现一个基于该接口的类,并传入该方法即可。

实现过程

创建必要的类

通过分析,我们首先要创建一个实现 Illuminate\Contracts\Pagination\Presenter 接口的实例。本文中案例中,我们在框架 app 目录下创建了一个类 NewPaginationPresenter, 命名空间是 App,该类实现上面我们讲的接口。

命名空间为什么是 App?因为 laravel 默认的,在 App 目录下的类命名空间一般都是 App(当然通过 artisan 命令修改过则以修改的为准),之后的 子命名空间 都按照 PSR-4 规范对应。

实现必要的方法

接口要求必须实现 hasPagerender 方法,其中 render 方法返回的值就是我们生成的目标 html 模板,因此我们主要就是实现这个方法。

对于 Laravel 默认的分页 html 代码的生成,是由 Illuminate\Pagination\BootstrapThreePresenter 类完成的,该类正是实现了之前我们说的那个接口,由于我们仅需要修改生成的 html 中的 dom 的 class 属性,所以我们没必要完完全全重写,只需要继承 Illuminate\Pagination\BootstrapThreePresenter 类,然后对其中的部分方法稍微改造即可

实际上我们通过文档也看得出一些端倪,laravel 的分页组件有 paginate 和 simplePaginate 两个方法,实际上这两个方法分别通过 Illuminate\Pagination 命名空间下的 BootstrapThreePresenter 类和 SimpleBootstrapThreePresenter 类生成目标 html,而 SimpleBootstrapThreePresenter 实际上只是继承 BootstrapThreePresenter,仅仅修改了其父类的两个方法而已。

我们创建的类同样可以继承 Illuminate\Pagination\BootstrapThreePresenter 类,我们的目的是让其生成符合 AmazeUI 分页组件的 html 代码格式。

默认 Illuminate\Pagination\BootstrapThreePresenter 有这样几个方法:

class BootstrapThreePresenter implements PresenterContract {

    // 此处省略

    public function render()
    {
        if ($this->hasPages())
        {
            return sprintf(
                '<ul class="pagination">%s %s %s</ul>',
                $this->getPreviousButton(),
                $this->getLinks(),
                $this->getNextButton()
            );
        }

        return '';
    }

    protected function getAvailablePageWrapper($url, $page, $rel = null)
    {
        $rel = is_null($rel) ? '' : ' rel="'.$rel.'"';

        return '<li><a href="'.htmlentities($url).'"'.$rel.'>'.$page.'</a></li>';
    }

    protected function getDisabledTextWrapper($text)
    {
        return '<li class="disabled"><span>'.$text.'</span></li>';
    }

    protected function getActivePageWrapper($text)
    {
        return '<li class="active"><span>'.$text.'</span></li>';
    }

    // 此处省略

}

通过发现,我们发现只需要修改上述代码中出现的 getActivePageWrapper、 getDisabledTextWrapper、 render 方法中的关于生成 html 的内容即可,比如 AmazeUI 的分页 html 结构和 Bootsrtap 一致,只是 CSS 选择器由 Bootstrap 的 .pagination 变为 .am-pagination 而已,那么我们就将 render 方法中的 .pagination 改为 .am-pagination 即可。其余的替换方式类似。

当然对于需求更多,则可以对 render 方法整体改造,总而言之,生成的 html 由该方法返回即可,至于生成什么、逻辑是什么样子的则由你来决定。

替换默认的生成类

我们知道,Pagination 组件的 render 方法实际上是调用 Presenter 接口实现的实例的 render 方法,通过将实例传入 render 即可。但是这样并不科学,首先是我们上面实现的 Presenter 实例的构造函数需要其他参数,同时还需要 Pagination 实例的传入!

这样看来十分麻烦且不实用。

但我们发现 Pagination 类有一个静态方法 presenter,该方法的作用就是注册默认 Presenter 实例,我们可以在任意位置(当然必须要在使用 Pagination 的 render 方法前)通过该静态方法注册默认 Presenter 实例即可。

为了方便全局使用,我们可以通过使用 Service Provider 在框架启动之初就注册该实例。

通过 artisan 创建一个 Service Provider,在 boot 方法中这样写:

<?php namespace App\Providers;

use App\NewPaginationPresenter;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Support\ServiceProvider;

class PaginationProvider extends ServiceProvider
{

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        // 使用自定义分页模板
        Paginator::presenter(function (AbstractPaginator $paginator) {
            return new NewPaginationPresenter($paginator);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

保存后,将该 Service Provider 加入 config 目录下的 app.php 配置文件的 providers 项里。好了,大功告成!!!

本帖已被设为精华帖!
本帖由系统于 6年前 自动加精
chongyi
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 4

这个处理思路非常好,很科学。

7年前 评论

请问能帮忙看下如何写AJAX的分页!

6年前 评论
chongyi

@LeO荣 直接返回分页对象啊,里面包含了需要分页的所有参数

6年前 评论

6.x 中没有 Illuminate\Contracts\Pagination\Presenter这个类了?

4年前 评论
chongyi (楼主) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!