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 相关文章推荐
模仿OSO的论坛(四)
Oct 09 PHP
php简单封装了一些常用JS操作
Feb 25 PHP
zen cart新进商品的随机排序修改方法
Sep 10 PHP
基于PHP5魔术常量与魔术方法的详解
Jun 13 PHP
php伪静态之APACHE篇
Jun 02 PHP
php自动识别文件编码并转换为UTF-8的方法
Jun 12 PHP
Yii中render和renderPartial的区别
Sep 03 PHP
PHP中使用匿名函数操作数据库的例子
Nov 17 PHP
php实现按指定大小等比缩放生成上传图片缩略图的方法
Dec 15 PHP
PHP版微信小店接口开发实例
Nov 12 PHP
php实现遍历文件夹的方法汇总
Mar 02 PHP
php多进程模拟并发事务产生的问题小结
Dec 07 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
ADODB类使用
2006/11/25 PHP
php FPDF类库应用实现代码
2009/03/20 PHP
Php Image Resize图片大小调整的函数代码
2011/01/17 PHP
使用GROUP BY的时候如何统计记录条数 COUNT(*) DISTINCT
2011/04/23 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
php获取YouTube视频信息的方法
2015/02/11 PHP
PHP实现腾讯与百度坐标转换
2017/08/05 PHP
[Web]防止用户复制页面内容和另存页面的方法
2009/02/06 Javascript
jQuery怎么解析Json字符串(Json格式/Json对象)
2013/08/09 Javascript
JS中图片缓冲loading技术的实例代码
2013/08/29 Javascript
jQuery循环动画与获取组件尺寸的方法
2015/02/02 Javascript
百度地图API之本地搜索与范围搜索
2015/07/30 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
JQuery统计input和textarea文字输入数量(代码分享)
2016/12/29 Javascript
VUE2实现事件驱动弹窗示例
2017/10/21 Javascript
jquery实现左右轮播切换效果
2018/01/01 jQuery
vue 使用饿了么UI仿写teambition的筛选功能
2021/03/01 Vue.js
Python实现根据指定端口探测服务器/模块部署的方法
2014/08/25 Python
Python简单获取自身外网IP的方法
2016/09/18 Python
Python正则表达式实现截取成对括号的方法
2017/01/06 Python
Python操作Sql Server 2008数据库的方法详解
2018/05/17 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
python3.x提取中文的正则表达式示例代码
2019/07/23 Python
Python Excel vlookup函数实现过程解析
2020/06/22 Python
Python中bisect的用法及示例详解
2020/07/20 Python
python的数学算法函数及公式用法
2020/11/18 Python
Python中全局变量和局部变量的理解与区别
2021/02/07 Python
详解python的xlwings库读写excel操作总结
2021/02/26 Python
如何执行一个shell程序
2012/11/23 面试题
黄继光的英雄事迹材料
2014/02/13 职场文书
文化建设工作方案
2014/05/12 职场文书
诉讼财产保全担保书
2014/05/20 职场文书
请客吃饭开场白
2015/06/01 职场文书
运动会闭幕式主持词
2015/07/01 职场文书
Vue实现跑马灯样式文字横向滚动
2021/11/23 Vue.js
Python OpenGL基本配置方式
2022/05/20 Python