laravel 手动分页

老表

很早就想记录一下,但是直到今天才有时间,目的就是希望大家可以避坑,下面进入正文

默认使用model方法paginate作为分页,其实laravel 里面已经做了很多处理,作为开发者来讲其实就想简简单单的调方法而已,但是事与愿违,总会有特殊的定制,下面就来讲讲怎么定义不一样的html

找到模版

找到Illuminate\Database\Eloquent\Builder.php类中的对应方法,实际上实例化的是LengthAwarePaginator这个类,传入了一些基本分页信息,
再根据namespace继续追代码 Illuminate\Pagination\LengthAwarePaginator
想到在视图中使用render 来渲染html代码,则观察下面方法

 public function render(Presenter $presenter = null)
 {
    if (is_null($presenter) && static::$presenterResolver) {
        $presenter = call_user_func(static::$presenterResolver, $this);
    }

    $presenter = $presenter ?: new BootstrapThreePresenter($this);

    return $presenter->render();
 }

看后面的代码可以知道这个Presenter 其实就是一个模版对象,这里暂且这样理解

创建自己的模版

下面有几个坑要注意

下面都以BootstrapThreePresenter举例

继承PresenterContract

\Illuminate\Contracts\Pagination\Presenter

观察 LengthAwarePaginator 类的同级目录下会发现好多个Presenter的类,我们打开 BootstrapThreePresenter 这个类就会发现继承了上面的这个Presenter接口,因为在其他的地方会有类型约束,也为了和laravel本身框架的代码风格保持一致,所以后面我们定义的模版也继承就可以了

生成html结构

恶心的地方来了。。。
这里引入了traits所以结构有些混乱,你别看定义了好几个方法,但是protected全tm在traits里面调用,我们看最主要的渲染方法

public function render()
{
    if ($this->hasPages()) {
        return sprintf(
            '<ul class="pagination">%s %s %s</ul>', //定义html容器
            $this->getPreviousButton(),  //生成上一页按钮
            $this->getLinks(), //生成中间的页码
            $this->getNextButton() //生成下一页按钮
        );
    }

    return '';
}

如果你还需要增加首页或者末页,只需要在<ul class="pagination">%s %s %s</ul>里面额外定义字符串参数就可以了

调用与封装

接下来我把项目中现成的代码拷贝过来

调用的封装

/**
 *
 * @return string 分页Html代码
 */
function pagination(\Illuminate\Contracts\Pagination\Paginator $paginator, $template = 'simple')
{
    //这里我定义了多个模版所以做了点处理
    $class = '\App\Libraries\Common\Pagination\\'.ucfirst($template).'Presenter';
    $paginator->setPath(request()->url());
    return $paginator
    ->appends(request()->input())
    ->render(new $class($paginator)); //实例化把自己传进去 我觉得恶心的不行,感觉像自己日自己
}

//demo
$paginate = User::paginate();
pagination($paginate, 'ajax');

SimplePresenter.php

<?php

namespace App\Libraries\Common\Pagination;

use Illuminate\Pagination\BootstrapThreeNextPreviousButtonRendererTrait;
use Illuminate\Pagination\UrlWindowPresenterTrait;
use Illuminate\Pagination\UrlWindow;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Contracts\Pagination\Presenter as PresenterContract;

class SimplePresenter implements PresenterContract
{
    //HeadTailButtonRendererTrait 这个是我自己定义的,用来创建首页与末页的按钮
    use BootstrapThreeNextPreviousButtonRendererTrait, HeadTailButtonRendererTrait,
    UrlWindowPresenterTrait;
    
    /**
     * The paginator implementation.
     *
     * @var \Illuminate\Contracts\Pagination\Paginator
     */
    protected $paginator;

    /**
     * The URL window data structure.
     *
     * @var array
     */
    protected $window;

    /**
     * Create a new Bootstrap presenter instance.
     *
     * @param  \Illuminate\Contracts\Pagination\Paginator  $paginator
     * @param  \Illuminate\Pagination\UrlWindow|null  $window
     * @return void
     */
    public function __construct(PaginatorContract $paginator, UrlWindow $window = null)
    {
        $this->paginator = $paginator;
        $this->window = is_null($window) ? UrlWindow::make($paginator) : $window->get();
    }

    /**
     * Determine if the underlying paginator being presented has pages to show.
     *
     * @return bool
     */
    public function hasPages()
    {
        return $this->paginator->hasPages();
    }

    /**
     * Convert the URL window into Bootstrap HTML.
     *
     * @return string
     */
    public function render()
    {
        if ($this->hasPages()) {
            return sprintf(
                '<div class="paging_box">%s %s %s %s %s</div>',
                $this->getLinks(),
                $this->getFirstButton('首页'),
                $this->getPreviousButton('上一页'),
                $this->getNextButton('下一页'),
                $this->getLastButton('末页')
            );
        }

        return '';
    }

    /**
     * Get HTML wrapper for an available page link.
     *
     * @param  string  $url
     * @param  int  $page
     * @param  string|null  $rel
     * @return string
     */
    protected function getAvailablePageWrapper($url, $page, $rel = null)
    {
        $rel = is_null($rel) ? '' : ' rel="'.$rel.'"';

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

    /**
     * Get HTML wrapper for disabled text.
     *
     * @param  string  $text
     * @return string
     */
    protected function getDisabledTextWrapper($text)
    {
        return '<a href="javascript:;">'.$text.'</a>';
    }

    /**
     * Get HTML wrapper for active text.
     *
     * @param  string  $text
     * @return string
     */
    protected function getActivePageWrapper($text)
    {
        return '<a href="javascript:;" class="on">'.$text.'</a>';
    }

    /**
     * Get a pagination "dot" element.
     *
     * @return string
     */
    protected function getDots()
    {
        return $this->getDisabledTextWrapper('...');
    }

    /**
     * Get the current page from the paginator.
     *
     * @return int
     */
    protected function currentPage()
    {
        return $this->paginator->currentPage();
    }

    /**
     * Get the last page from the paginator.
     *
     * @return int
     */
    protected function lastPage()
    {
        return $this->paginator->lastPage();
    }

    
}

我的方式可能不是最优雅的,也可能会有其他方法,但是我这里只介绍一个思路,不做其他尝试

阅读 3.4k

2.1k 声望
103 粉丝
0 条评论
2.1k 声望
103 粉丝
文章目录
宣传栏