本文最先发表于本人博客: Laravel5.1+ 分页Pagination解析以及扩展php
Laravel 的分页很方便,其实扩展起来也挺容易的,下面就来作个示例,扩展一下paginate()
和 simplePaginate()
方法,来实现咱们自定义分页样式,好比显示"上一页"和"下一页",而不是"《"和"》",固然扩展的方法掌握了你就能够肆无忌惮的扩展一个你想要的分页了,好比跳转到某一页,分页显示一共多少记录,当前显示的记录范围等等巴拉巴拉的。。。html
5.1和5.2应该是一样的方法,我这里用的是5.2的版本。文档告诉咱们Paginator
对应于查询语句构造器和 Eloquent 的 simplePaginate
方法,而 LengthAwarePaginator
则等同于 paginate
方法。那咱们仍是来看下源码,具体这个 paginate
是如何实现render()
的,laravel
<?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
是干吗的web
<?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</ul>', $this->getPreviousButton(), $this->getLinks(), $this->getNextButton() )); } return ''; } ...... }
这里能够看到BootstrapThreePresenter
实现了PresenterContract
的接口,render()
才是分页显示的真正实现,构造方法中的第一个参数PaginatorContract
其实就是一个Paginator
咱们继续看下PresenterContract
也就是Presenter
接口中定义了什么方法须要实现app
<?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
方法须要实现ide
好了,那咱们如今已经很清晰了,咱们要自定义分页的显示,那么就要写一个咱们本身的Presenter
来实现接口中的render()
和hasPages()
就能够了。this
首先就来简单的实现一个paginate(),显示出来"上一页"和"下一页",中间是分页数字的例子。url
新建文件以下(我的习惯)app/Foundations/Pagination/CustomerPresenter.phpspa
<?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, 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</ul>', $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"><span>' . $text . '</span></li>'; } /** * Get HTML wrapper for active text. * * @param string $text * @return string */ protected function getActivePageWrapper($text) { return '<li class="active"><span>' . $text . '</span></li>'; } /** * 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
,默认的分页显示是这样的:code
{!! $users->render() !!}
修改为咱们自定义后的分页显示:
{!! with(new \App\Foundations\Pagination\CustomerPresenter($categories))->render() !!}
好了,这样在页面应该就能够看到分页连接中含有 "上一页"和"下一页"加数字的样式了。
那么若是扩展simplePaginate?其实很简单,只要继承刚才的CustomerPresenter
,实现hasPages
和render
,至于为何能够按照我上面查看源码的方式看一下就知道了,好比咱们改为"上一篇"和"下一篇"
新建AppFoundationsPaginationCustomerSimplePresenter.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</ul>', $this->getPreviousButton('上一篇'), $this->getNextButton('下一篇') )); } return ''; } }
分页显示:
{!! with(new \App\Foundations\Pagination\CustomerSimplePresenter($categories))->render() !!}
方法就是这个方法,具体修改按照本身需求重写其中对应的显示html元素的方法就能够了。
若是以为本篇文章对您十分有益,何不 打赏一下