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


Posted in PHP onApril 22, 2020

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</ul>',
    $this->getPreviousButton(),
    $this->getLinks(),
    $this->getNextButton()
   ));
  }

  return '';
 }
......
}

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

illuminate/contracts/Pagination/Presenter.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

<?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 ,默认的分页显示是这样的:

{!! $users->render() !!}
修改成我们自定义后的分页显示:

{!! with(new \App\Foundations\Pagination\CustomerPresenter($categories))->render() !!}
好了,这样在页面应该就可以看到分页链接中含有 "上一页"和"下一页"加数字的样式了。

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

新建App\Foundations\Pagination\CustomerSimplePresenter.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元素的方法就可以了。

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

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

PHP 相关文章推荐
php 获得汉字拼音首字母的函数
Aug 01 PHP
iis下php mail函数的sendmail配置方法(官方推荐)
Apr 25 PHP
PHP 函数call_user_func和call_user_func_array用法详解
Mar 02 PHP
ThinkPHP提交表单时默认自动转义的解决方法
Nov 25 PHP
phpstorm配置Xdebug进行调试PHP教程
Dec 01 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
Jan 17 PHP
PHP对称加密算法(DES/AES)类的实现代码
Nov 14 PHP
PHP封装的XML简单操作类完整实例
Nov 13 PHP
PHP使用标准库spl实现的观察者模式示例
Aug 04 PHP
PHP使用SMTP邮件服务器发送邮件示例
Aug 28 PHP
Yii2框架控制器、路由、Url生成操作示例
May 27 PHP
PHP使用ajax的post方式下载excel文件简单示例
Aug 06 PHP
屏蔽PHP默认设置中的Notice警告的方法
May 20 #PHP
PHP获取网站中各文章的第一张图片的代码示例
May 20 #PHP
今天你说520了吗?不仅有php表白书还有java表白神器
May 20 #PHP
程序员的表白神器“520”大声喊出来
May 20 #PHP
PHP性能优化大全(php.ini)
May 20 #PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
May 20 #PHP
smarty自定义函数用法示例
May 20 #PHP
You might like
php 获取select下拉列表框的值
2010/05/08 PHP
php获取301跳转URL简单实例
2013/12/16 PHP
PHP简单创建压缩图的方法
2016/08/24 PHP
php+mysql查询实现无限下级分类树输出示例
2016/10/03 PHP
php 算法之实现相对路径的实例
2017/10/17 PHP
jQuery 选择器理解
2010/03/16 Javascript
JS target与currentTarget区别说明
2011/08/28 Javascript
JavaScript自定义DateDiff函数(兼容所有浏览器)
2012/03/01 Javascript
iframe窗口高度自适应的实现方法
2014/01/08 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
2015/03/18 Javascript
分享10个优化代码的CSS和JavaScript工具
2016/05/11 Javascript
Node.js操作redis实现添加查询功能
2017/05/25 Javascript
详解vue-router2.0动态路由获取参数
2017/06/14 Javascript
bootstrap响应式导航条模板使用详解(含下拉菜单,弹出框)
2017/11/17 Javascript
使用vue自定义指令开发表单验证插件validate.js
2019/05/23 Javascript
python解析xml文件实例分享
2013/12/04 Python
Windows下Python的Django框架环境部署及应用编写入门
2016/03/10 Python
Python使用matplotlib填充图形指定区域代码示例
2018/01/16 Python
python实现zabbix发送短信脚本
2018/09/17 Python
Python中is和==的区别详解
2018/11/15 Python
一篇文章搞懂Python的类与对象名称空间
2018/12/10 Python
python时间序列按频率生成日期的方法
2019/05/14 Python
python 自定义装饰器实例详解
2019/07/20 Python
django+tornado实现实时查看远程日志的方法
2019/08/12 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
Python列表切片常用操作实例解析
2020/03/10 Python
加拿大快时尚零售商:Ardene
2018/02/14 全球购物
美国值得信赖的婚恋交友网站:eHarmony
2018/10/04 全球购物
优秀学生获奖感言
2014/02/15 职场文书
同学聚会策划方案
2014/06/06 职场文书
医生辞职信范文
2015/03/02 职场文书
2015年村党支部工作总结
2015/04/30 职场文书
无婚姻登记记录证明
2015/06/18 职场文书
呼兰河传读书笔记
2015/06/30 职场文书
导游词之长城八达岭
2019/09/24 职场文书
零基础学java之带返回值的方法的定义和调用
2022/04/10 Java/Android