PHP框架Laravel插件Pagination实现自定义分页

Laravel 的分页很方便,其实扩展起来也挺容易的,下面就来做个示例,扩展一下 paginate() 和 simplePaginate() 方法,来实现我们自定义分页样式,比如显示 "上一页" 和 "下一页" ,而不是 "《" 和 "》" ,当然扩展的方法掌握了你就可以肆无忌惮的扩展一个你想要的分页了,比如跳转到某一页,分页显示一共多少记录,当前显示的记录范围等等巴拉巴拉的。。。

5.1和5.2应该是同样的方法,我这里用的是5.2的版本。文档告诉我们 Paginator 对应于查询语句构造器和 Eloquent 的 simplePaginate 方法,而 LengthAwarePaginator 则等同于 paginate 方法。那我们还是来看下源码,具体这个 paginate 是如何实现 render() 的,

Illuminate/Pagination/LengthAwarePaginator.PHP

PHP;"> namespace Illuminate\Pagination;

......

class LengthAwarePaginator extends AbstractPaginator implements Arrayable,ArrayAccess,Countable,IteratorAggregate,JsonSerializable,Jsonable,LengthAwarePaginatorContract
{
......
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();

}
......
}

render() 中传入的是一个 Presenter 的实例,并调用这个实例化的 render 方法来实现分页显示的。如果没有则调用 BootstrapThreePresenter 中 render() 的,来看看 BootstrapThreePresenter 是干嘛的

Illuminate/Pagination/BootstrapThreePresenter.PHP

PHP;"> namespace Illuminate\Pagination;

use Illuminate\Support\HtmlString;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Contracts\Pagination\Presenter as PresenterContract;

class BootstrapThreePresenter implements PresenterContract
{
use BootstrapThreeNextPreviousButtonRendererTrait,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 \Illuminate\Support\HtmlString
    */
    public function render()
    {
    if ($this->hasPages()) {
    return new HtmlString(sprintf(
    '<ul class="pagination">%s %s %s
',$this->getPrevIoUsButton(),$this->getLinks(),$this->getNextButton()
));
}
return '';

}
......
}

这里可以看到 BootstrapThreePresenter 实现了 PresenterContract 的接口, render() 才是分页显示的真正实现,构造方法中的第一个参数 PaginatorContract 其实就是一个 Paginator 我们继续看下 PresenterContract 也就是 Presenter 接口中定义了什么方法需要实现

illuminate/contracts/Pagination/Presenter.PHP

PHP;"> PHP

namespace Illuminate\Contracts\Pagination;

interface Presenter
{
/**

  • Render the given paginator.
  • @return \Illuminate\Contracts\Support\Htmlable|string
    */
    public function render();

/**

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

其中定义了 render 和 hasPages 方法需要实现

好了,那我们现在已经很清晰了,我们要自定义分页显示,那么就要写一个我们自己的 Presenter 来实现接口中的 render() 和 hasPages() 就可以了。

首先就来简单的实现一个paginate(),显示出来"上一页"和"下一页",中间是分页数字的例子。

新建文件如下(个人习惯)

app/Foundations/Pagination/CustomerPresenter.PHP

<div class="jb51code">
<pre class="brush:PHP;">
<?php
namespace App\Foundations\Pagination;

use Illuminate\Contracts\Pagination\Presenter as PresenterContract;
use Illuminate\Contracts\Pagination\LengthAwarePaginator as PaginatorContract;
use Illuminate\Pagination\UrlWindow;
use Illuminate\Support\HtmlString;
use Illuminate\Pagination\BootstrapThreeNextPreviousButtonRendererTrait;
use Illuminate\Pagination\UrlWindowPresenterTrait;

class CustomerPresenter implements PresenterContract
{
use BootstrapThreeNextPreviousButtonRendererTrait,UrlWindowPresenterTrait;

protected $paginator;

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,$this->getPrevIoUsButton('上一页'),//具体实现可以查看该方法
    $this->getLinks(),$this->getNextButton('下一页')//具体实现可以查看该方法
    ));
    }
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 '<li><a href="' . htmlentities($url) . '"' . $rel . '>' . $page . '</a></li>';

}

/**

  • Get HTML wrapper for disabled text.
  • @param string $text
  • @return string
    */
    protected function getDisabledTextWrapper($text)
    {
    return '<li class="disabled hide">' . $text . '
  • ';
    }

/**

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

/**

  • 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();
    }

}

就这么简单,主要就是 render() 方法,如果项目中需要修改分页样式,或者添加分页跳转之类的需求只要重写其中的各项显示方法中的html元素就可以了,很灵活,在blade模板中也需要修该,比如我们的 Paginator 叫 $users,默认的分页显示是这样的:

render() !!} 修改成我们自定义后的分页显示

render() !!} 好了,这样在页面应该就可以看到分页链接中含有 "上一页"和"下一页"加数字的样式了。

那么如果扩展simplePaginate?其实很简单,只要继承刚才的 CustomerPresenter ,实现 hasPages 和 render,至于为什么可以按照我上面查看源码的方式看一下就知道了,比如我们改成"上一篇"和"下一篇"

新建App\Foundations\Pagination\CustomerSimplePresenter.PHP

<div class="jb51code">
<pre class="brush:PHP;">
<?php
namespace App\Foundations\Pagination;

use Illuminate\Support\HtmlString;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;

class CustomerSimplePresenter extends CustomerPresenter
{
/**

  • Create a simple Bootstrap 3 presenter.
  • @param \Illuminate\Contracts\Pagination\Paginator $paginator
  • @return void
    */
    public function __construct(PaginatorContract $paginator)
    {
    $this->paginator = $paginator;
    }

/**

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

/**

  • Convert the URL window into Bootstrap HTML.
  • @return \Illuminate\Support\HtmlString
    */
    public function render()
    {
    if ($this->hasPages()) {
    return new HtmlString(sprintf(
    '<ul class="pager">%s %s
',$this->getPrevIoUsButton('上一篇'),$this->getNextButton('下一篇')
));
}
return '';

}

}

分页显示

render() !!}

方法就是这个方法,具体修改按照自己需求重写其中对应的显示html元素的方法就可以了。

转载请注明:转载自 Ryan是菜鸟 | LNMP技术栈笔记

以上就是本文的全部内容,希望对大家学习PHP程序设计有所帮助。

相关文章

[laravel] laravel的数据库配置 找到程序目录结构下.env文件 配置基本的数据库连接信息 DB_HOST=127.0....
[Laravel] Laravel的基本HTTP路由 使用Laravel的基本路由,实现get请求响应,找到文件app/Http/routes....
如果说laravel框架的核心是什么,那么无疑是服务容器。理解服务容器的概念,对于我们使用laravel太重要...
网上有很多解析laravel中间件的实现原理,但是不知道有没有读者在读的时候不明白,作者是怎么想到要用a...
laraveli添加一个或多个用户表,以admin为例。 部分文件内容可能需要根据实际情况修改 创建一个Admin模...
TL;DR: 本文介绍 Laravel 的 FastExcel 组件,文中会对 PHP generators 速览,并给出如何在节约内存的同...