PHP框架Laravel插件Pagination实现自定义分页
Laravel的分页很方便,其实扩展起来也挺容易的,下面就来做个示例,扩展一下paginate()和simplePaginate()方法,来实现我们自定义分页样式,比如显示"上一页"和"下一页",而不是"《"和"》",当然扩展的方法掌握了你就可以肆无忌惮的扩展一个你想要的分页了,比如跳转到某一页,分页显示一共多少记录,当前显示的记录范围等等巴拉巴拉的。
5.1和5.2应该是同样的方法,我这里用的是5.2的版本。文档告诉我们Paginator对应于查询语句构造器和Eloquent的 simplePaginate方法,而 LengthAwarePaginator则等同于 paginate方法。那我们还是来看下源码,具体这个 paginate是如何实现render()的,
Illuminate/Pagination/LengthAwarePaginator.php
<?php namespaceIlluminate\Pagination; ...... classLengthAwarePaginatorextendsAbstractPaginatorimplementsArrayable,ArrayAccess,Countable,IteratorAggregate,JsonSerializable,Jsonable,LengthAwarePaginatorContract { ...... publicfunctionrender(Presenter$presenter=null) { if(is_null($presenter)&&static::$presenterResolver){ $presenter=call_user_func(static::$presenterResolver,$this); } $presenter=$presenter?:newBootstrapThreePresenter($this); return$presenter->render(); } ...... }
render()中传入的是一个Presenter的实例,并调用这个实例化的render方法来实现分页的显示的。如果没有则调用BootstrapThreePresenter中render()的,来看看BootstrapThreePresenter是干嘛的
Illuminate/Pagination/BootstrapThreePresenter.php
<?php namespaceIlluminate\Pagination; useIlluminate\Support\HtmlString; useIlluminate\Contracts\Pagination\PaginatorasPaginatorContract; useIlluminate\Contracts\Pagination\PresenterasPresenterContract; classBootstrapThreePresenterimplementsPresenterContract { useBootstrapThreeNextPreviousButtonRendererTrait,UrlWindowPresenterTrait; /** *Thepaginatorimplementation. * *@var\Illuminate\Contracts\Pagination\Paginator */ protected$paginator; /** *TheURLwindowdatastructure. * *@vararray */ protected$window; /** *CreateanewBootstrappresenterinstance. * *@param\Illuminate\Contracts\Pagination\Paginator$paginator *@param\Illuminate\Pagination\UrlWindow|null$window *@returnvoid */ publicfunction__construct(PaginatorContract$paginator,UrlWindow$window=null) { $this->paginator=$paginator; $this->window=is_null($window)?UrlWindow::make($paginator):$window->get(); } /** *Determineiftheunderlyingpaginatorbeingpresentedhaspagestoshow. * *@returnbool */ publicfunctionhasPages() { return$this->paginator->hasPages(); } /** *ConverttheURLwindowintoBootstrapHTML. * *@return\Illuminate\Support\HtmlString */ publicfunctionrender() { if($this->hasPages()){ returnnewHtmlString(sprintf( '<ulclass="pagination">%s%s%s</ul>', $this->getPreviousButton(), $this->getLinks(), $this->getNextButton() )); } return''; } ...... }
这里可以看到BootstrapThreePresenter实现了PresenterContract的接口,render()才是分页显示的真正实现,构造方法中的第一个参数PaginatorContract其实就是一个Paginator我们继续看下PresenterContract也就是Presenter接口中定义了什么方法需要实现
illuminate/contracts/Pagination/Presenter.php
<?php namespaceIlluminate\Contracts\Pagination; interfacePresenter { /** *Renderthegivenpaginator. * *@return\Illuminate\Contracts\Support\Htmlable|string */ publicfunctionrender(); /** *Determineiftheunderlyingpaginatorbeingpresentedhaspagestoshow. * *@returnbool */ publicfunctionhasPages(); }
其中定义了render和hasPages方法需要实现
好了,那我们现在已经很清晰了,我们要自定义分页的显示,那么就要写一个我们自己的Presenter来实现接口中的render()和hasPages()就可以了。
首先就来简单的实现一个paginate(),显示出来"上一页"和"下一页",中间是分页数字的例子。
新建文件如下(个人习惯)
app/Foundations/Pagination/CustomerPresenter.php
<?php namespaceApp\Foundations\Pagination; useIlluminate\Contracts\Pagination\PresenterasPresenterContract; useIlluminate\Contracts\Pagination\LengthAwarePaginatorasPaginatorContract; useIlluminate\Pagination\UrlWindow; useIlluminate\Support\HtmlString; useIlluminate\Pagination\BootstrapThreeNextPreviousButtonRendererTrait; useIlluminate\Pagination\UrlWindowPresenterTrait; classCustomerPresenterimplementsPresenterContract { useBootstrapThreeNextPreviousButtonRendererTrait,UrlWindowPresenterTrait; protected$paginator; protected$window; /** *CreateanewBootstrappresenterinstance. * *@param\Illuminate\Contracts\Pagination\Paginator$paginator *@param\Illuminate\Pagination\UrlWindow|null$window *@returnvoid */ publicfunction__construct(PaginatorContract$paginator,UrlWindow$window=null) { $this->paginator=$paginator; $this->window=is_null($window)?UrlWindow::make($paginator):$window->get(); } /** *Determineiftheunderlyingpaginatorbeingpresentedhaspagestoshow. * *@returnbool */ publicfunctionhasPages() { return$this->paginator->hasPages(); } /** *ConverttheURLwindowintoBootstrapHTML. * *@return\Illuminate\Support\HtmlString */ publicfunctionrender() { if($this->hasPages()){ returnnewHtmlString(sprintf( '<ulclass="pagination">%s%s%s</ul>', $this->getPreviousButton('上一页'),//具体实现可以查看该方法 $this->getLinks(), $this->getNextButton('下一页')//具体实现可以查看该方法 )); } return''; } /** *GetHTMLwrapperforanavailablepagelink. * *@paramstring$url *@paramint$page *@paramstring|null$rel *@returnstring */ protectedfunctiongetAvailablePageWrapper($url,$page,$rel=null) { $rel=is_null($rel)?'':'rel="'.$rel.'"'; return'<li><ahref="'.htmlentities($url).'"'.$rel.'>'.$page.'</a></li>'; } /** *GetHTMLwrapperfordisabledtext. * *@paramstring$text *@returnstring */ protectedfunctiongetDisabledTextWrapper($text) { return'<liclass="disabledhide"><span>'.$text.'</span></li>'; } /** *GetHTMLwrapperforactivetext. * *@paramstring$text *@returnstring */ protectedfunctiongetActivePageWrapper($text) { return'<liclass="active"><span>'.$text.'</span></li>'; } /** *Getapagination"dot"element. * *@returnstring */ protectedfunctiongetDots() { return$this->getDisabledTextWrapper('...'); } /** *Getthecurrentpagefromthepaginator. * *@returnint */ protectedfunctioncurrentPage() { return$this->paginator->currentPage(); } /** *Getthelastpagefromthepaginator. * *@returnint */ protectedfunctionlastPage() { return$this->paginator->lastPage(); } }
就这么简单,主要就是render()方法,如果项目中需要修改分页样式,或者添加分页跳转之类的需求只要重写其中的各项显示的方法中的html元素就可以了,很灵活,在blade模板中也需要修该,比如我们的Paginator叫$users,默认的分页显示是这样的:
{!!$users->render()!!}
修改成我们自定义后的分页显示:
{!!with(new\App\Foundations\Pagination\CustomerPresenter($categories))->render()!!}
好了,这样在页面应该就可以看到分页链接中含有"上一页"和"下一页"加数字的样式了。
那么如果扩展simplePaginate?其实很简单,只要继承刚才的CustomerPresenter,实现hasPages和render,至于为什么可以按照我上面查看源码的方式看一下就知道了,比如我们改成"上一篇"和"下一篇"
新建App\Foundations\Pagination\CustomerSimplePresenter.php
<?php namespaceApp\Foundations\Pagination; useIlluminate\Support\HtmlString; useIlluminate\Contracts\Pagination\PaginatorasPaginatorContract; classCustomerSimplePresenterextendsCustomerPresenter { /** *CreateasimpleBootstrap3presenter. * *@param\Illuminate\Contracts\Pagination\Paginator$paginator *@returnvoid */ publicfunction__construct(PaginatorContract$paginator) { $this->paginator=$paginator; } /** *Determineiftheunderlyingpaginatorbeingpresentedhaspagestoshow. * *@returnbool */ publicfunctionhasPages() { return$this->paginator->hasPages()&&count($this->paginator->items())>0; } /** *ConverttheURLwindowintoBootstrapHTML. * *@return\Illuminate\Support\HtmlString */ publicfunctionrender() { if($this->hasPages()){ returnnewHtmlString(sprintf( '<ulclass="pager">%s%s</ul>', $this->getPreviousButton('上一篇'), $this->getNextButton('下一篇') )); } return''; } }
分页显示:
{!!with(new\App\Foundations\Pagination\CustomerSimplePresenter($categories))->render()!!}
方法就是这个方法,具体修改按照自己需求重写其中对应的显示html元素的方法就可以了。
转载请注明:转载自Ryan是菜鸟|LNMP技术栈笔记
以上就是本文的全部内容,希望对大家学习PHP程序设计有所帮助。