thinkphp(tp)中分页方法paginate的学习
学习初衷:不想用官方给的模板渲染方式,只想接受数据。
- 官方给的模板渲染:
// 查询状态为1的用户数据 并且每页显示10条数据$list = Db::name('userhttps://blog.csdn.net/qq_45764833/article/details/')->where('statushttps://blog.csdn.net/qq_45764833/article/details/',1)->paginate(10);// 渲染模板输出return view('indexhttps://blog.csdn.net/qq_45764833/article/details/', ['listhttps://blog.csdn.net/qq_45764833/article/details/' => $list]);// 模板文件中分页输出代码如下:<div><ul>{volist name='listhttps://blog.csdn.net/qq_45764833/article/details/' id='userhttps://blog.csdn.net/qq_45764833/article/details/'} <li> {$user.nickname}</li>{/volist}</ul></div>{$list|raw}
- 而我只单纯想要返回的数据
// 查询状态为1的用户数据 并且每页显示10条数据$list = Db::name('userhttps://blog.csdn.net/qq_45764833/article/details/')->where('statushttps://blog.csdn.net/qq_45764833/article/details/',1)->paginate(10);// 只输出数据return $list;
- $list return 后的格式为
// 这为官方返回的格式{"total": 2,"per_page": 10,"current_page": 1,"last_page": 1,"data": [{"id": 1,"file_id": 1,"acc_set": "A"},{"id": 2,"file_id": 1,"acc_set": "A"}]}
那么问题来了:怎么获取上图中像"total"、"data"这样的值
先说结论:
// 取"total"值$list -> toArray()['totalhttps://blog.csdn.net/qq_45764833/article/details/']; // 返回2// 取"data"值$list -> toArray()['datahttps://blog.csdn.net/qq_45764833/article/details/']; // 返回aray数组
如果你急着想知道怎么获取数据,读到这就可以结束了。
如果你想知道我解决这个问题的思路,请继续往下看。
获得所有数据的思考流程
刚拿到数据的处理方式
{"total": 2,"per_page": 10,"current_page": 1,"last_page": 1,"data": [{"id": 1,"file_id": 1,"acc_set": "A"},{"id": 2,"file_id": 1,"acc_set": "A"}]}
我想当然认为是数组,就用下面方式
// 取"total"值return $list ['totalhttps://blog.csdn.net/qq_45764833/article/details/'];
结果控制台显示 :
说明这不是数组类型。我又想是不是json格式的,就想转为数组:
// 将json数据转为数组,第二个参数改为‘false’,则转为对象$list = json_decode($list, true);return $list;
结果和上图一样,还是没有响应数据。
var_dump()函数查看数据类型
至此,我只能通过var_dump()函数来看看你是神马?
// var_dump()函数可以查看数据类型return var_dump($list);
结果是这个玩意:
object(think\paginator\driver\Bootstrap)#91 (8) { ["simple":protected]=> bool(false) ["items":protected]=> object(think\Collection)#83 (1) { ["items":protected]=> array(2) { [0]=> array(3) { ["id"]=> int(1) ["file_id"]=> int(1) ["acc_set"]=> string(1) "A" } [1]=> array(3) { ["id"]=> int(2) ["file_id"]=> int(1) ["acc_set"]=> string(1) "A" } } } ["currentPage":protected]=> int(1) ["lastPage":protected]=> int(1) ["total":protected]=> int(2) ["listRows":protected]=> int(10) ["hasMore":protected]=> bool(false) ["options":protected]=> array(6) { ["var_page"]=> string(4) "page" ["path"]=> string(34) "/index.php/admin/vouch_info/search" ["query"]=> array(0) { } ["fragment"]=> string(0) "" ["list_rows"]=> string(2) "10" ["page"]=> int(1) }}
可以看出是一个think\paginator\driver\Bootstrap对象,由于每个属性都是protected,所以也没法直接调用($list -> total)。
那接下来就是找源码。主要涉及两个源码:Bootstrap和Paginator(Bootstrap extends Paginator),这两个源码在文章最后。
我找源码的方式:
在任意控制器里使用下图方式引入,然后crtl+鼠标左键
use think\paginator\driver\Bootstrap;
Bootstrap部分源码
这两个源码也不难,简单来说Paginator类就是对分页所有数据进行处理,而Bootstrap类是将Paginator类处理好的数据渲染到模板上。
Bootstrap类所有方法都是生成什么什么按钮,只有一个render()方法是最核心的,他就是将按钮渲染到页面上。
public function render() { if ($this->hasPages()) { if ($this->simple) { return sprintf( '%s %s
https://blog.csdn.net/qq_45764833/article/details/', $this->getPreviousButton(), // 上一页按钮 $this->getNextButton()// 下一页按钮 ); } else { return sprintf( '%s %s %s
https://blog.csdn.net/qq_45764833/article/details/', $this->getPreviousButton(),// 上一页按钮 $this->getLinks(),// 页码按钮 $this->getNextButton()// 下一页按钮 ); } } }
读到这,官方文档中这句话你就明白什么意思了:
// 获取分页显示$page = $list->render();
所以Bootstrap类比较简单,如果只想获取数据的话用不到这个类,所以要调用父类Paginator中方法。
Paginator类部分源码
Paginator类定义了很多属性和方法,每一个都解释篇幅太长,而且我还是刚毕业且刚转正的菜鸟,估计也很难都解释清楚。这不重要,重要的是如何获得$list中的数据。直接将Paginator类中的代码拉到底,你会看到如下方法:
public function toArray(): array { try { $total = $this->total(); } catch (DomainException $e) { $total = null; } return [ 'totalhttps://blog.csdn.net/qq_45764833/article/details/' => $total, 'per_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->listRows(), 'current_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->currentPage(), 'last_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->lastPage, 'datahttps://blog.csdn.net/qq_45764833/article/details/' => $this->items->toArray(), ]; } public function jsonSerialize() { return $this->toArray(); }
下面的jsonSerialize()方法也是调用toArray(),所以toArray()方法算是提供给开发人员获取Paginator类中其他所有方法处理后得到的最终数据的接口。最后所有数据都会放在toArray()方法生成的数组中,尽情使用吧!
当然,想使用模板渲染方式的,请参考官方手册
基本使用(参考ThinkPHP6.0完全开发手册)
Bootstrap和Paginator源码(tp6)
- Bootstrap源码
// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK ]// +----------------------------------------------------------------------// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: zhangyajun <448901948@qq.com>// +----------------------------------------------------------------------namespace think\paginator\driver;use think\Paginator;class Bootstrap extends Paginator{ protected function getPreviousButton(string $text = "«"): string { if ($this->currentPage() <= 1) { return $this->getDisabledTextWrapper($text); } $url = $this->url( $this->currentPage() - 1 ); return $this->getPageLinkWrapper($url, $text); } protected function getNextButton(string $text = '»https://blog.csdn.net/qq_45764833/article/details/'): string { if (!$this->hasMore) { return $this->getDisabledTextWrapper($text); } $url = $this->url($this->currentPage() + 1); return $this->getPageLinkWrapper($url, $text); } protected function getLinks(): string { if ($this->simple) { return 'https://blog.csdn.net/qq_45764833/article/details/'; } $block = [ 'firsthttps://blog.csdn.net/qq_45764833/article/details/' => null, 'sliderhttps://blog.csdn.net/qq_45764833/article/details/' => null, 'lasthttps://blog.csdn.net/qq_45764833/article/details/' => null, ]; $side = 3; $window = $side * 2; if ($this->lastPage < $window + 6) { $block['firsthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange(1, $this->lastPage); } elseif ($this->currentPage <= $window) { $block['firsthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange(1, $window + 2); $block['lasthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage); } elseif ($this->currentPage > ($this->lastPage - $window)) { $block['firsthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange(1, 2); $block['lasthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange($this->lastPage - ($window + 2), $this->lastPage); } else { $block['firsthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange(1, 2); $block['sliderhttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange($this->currentPage - $side, $this->currentPage + $side); $block['lasthttps://blog.csdn.net/qq_45764833/article/details/'] = $this->getUrlRange($this->lastPage - 1, $this->lastPage); } $html = 'https://blog.csdn.net/qq_45764833/article/details/'; if (is_array($block['firsthttps://blog.csdn.net/qq_45764833/article/details/'])) { $html .= $this->getUrlLinks($block['firsthttps://blog.csdn.net/qq_45764833/article/details/']); } if (is_array($block['sliderhttps://blog.csdn.net/qq_45764833/article/details/'])) { $html .= $this->getDots(); $html .= $this->getUrlLinks($block['sliderhttps://blog.csdn.net/qq_45764833/article/details/']); } if (is_array($block['lasthttps://blog.csdn.net/qq_45764833/article/details/'])) { $html .= $this->getDots(); $html .= $this->getUrlLinks($block['lasthttps://blog.csdn.net/qq_45764833/article/details/']); } return $html; } public function render() { if ($this->hasPages()) { if ($this->simple) { return sprintf( '%s %s
https://blog.csdn.net/qq_45764833/article/details/', $this->getPreviousButton(), $this->getNextButton() ); } else { return sprintf( '%s %s %s
https://blog.csdn.net/qq_45764833/article/details/', $this->getPreviousButton(), $this->getLinks(), $this->getNextButton() ); } } } protected function getAvailablePageWrapper(string $url, string $page): string { return '. htmlentities($url) . '">https://blog.csdn.net/qq_45764833/article/details/' . $page . 'https://blog.csdn.net/qq_45764833/article/details/'; } protected function getDisabledTextWrapper(string $text): string { return 'https://blog.csdn.net/qq_45764833/article/details/' . $text . https://blog.csdn.net/qq_45764833/article/details/' https://blog.csdn.net/qq_45764833/article/details/'; } protected function getActivePageWrapper(string $text): string { return 'https://blog.csdn.net/qq_45764833/article/details/' . $text . https://blog.csdn.net/qq_45764833/article/details/' https://blog.csdn.net/qq_45764833/article/details/'; } protected function getDots(): string { return $this->getDisabledTextWrapper('...https://blog.csdn.net/qq_45764833/article/details/'); } protected function getUrlLinks(array $urls): string { $html = 'https://blog.csdn.net/qq_45764833/article/details/'; foreach ($urls as $page => $url) { $html .= $this->getPageLinkWrapper($url, $page); } return $html; } protected function getPageLinkWrapper(string $url, string $page): string { if ($this->currentPage() == $page) { return $this->getActivePageWrapper($page); } return $this->getAvailablePageWrapper($url, $page); }}
- Paginator源码
// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK ]// +----------------------------------------------------------------------// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: zhangyajun <448901948@qq.com>// +----------------------------------------------------------------------declare (strict_types = 1);namespace think;use ArrayAccess;use ArrayIterator;use Closure;use Countable;use DomainException;use IteratorAggregate;use JsonSerializable;use think\paginator\driver\Bootstrap;use Traversable;abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable{ protected $simple = false; protected $items; protected $currentPage; protected $lastPage; protected $total; protected $listRows; protected $hasMore; protected $options = [ 'var_pagehttps://blog.csdn.net/qq_45764833/article/details/' => 'pagehttps://blog.csdn.net/qq_45764833/article/details/', 'pathhttps://blog.csdn.net/qq_45764833/article/details/' => '/https://blog.csdn.net/qq_45764833/article/details/', 'queryhttps://blog.csdn.net/qq_45764833/article/details/' => [], 'fragmenthttps://blog.csdn.net/qq_45764833/article/details/' => 'https://blog.csdn.net/qq_45764833/article/details/', ]; protected static $currentPageResolver; protected static $currentPathResolver; protected static $maker; public function __construct($items, int $listRows, int $currentPage = 1, int $total = null, bool $simple = false, array $options = []) { $this->options = array_merge($this->options, $options); $this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/'] = '/https://blog.csdn.net/qq_45764833/article/details/' != $this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/'] ? rtrim($this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/'], '/https://blog.csdn.net/qq_45764833/article/details/') : $this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/']; $this->simple = $simple; $this->listRows = $listRows; if (!$items instanceof Collection) { $items = Collection::make($items); } if ($simple) { $this->currentPage = $this->setCurrentPage($currentPage); $this->hasMore = count($items) > ($this->listRows); $items = $items->slice(0, $this->listRows); } else { $this->total = $total; $this->lastPage = (int) ceil($total / $listRows); $this->currentPage = $this->setCurrentPage($currentPage); $this->hasMore = $this->currentPage < $this->lastPage; } $this->items = $items; } public static function make($items, int $listRows, int $currentPage = 1, int $total = null, bool $simple = false, array $options = []) { if (isset(static::$maker)) { return call_user_func(static::$maker, $items, $listRows, $currentPage, $total, $simple, $options); } return new Bootstrap($items, $listRows, $currentPage, $total, $simple, $options); } public static function maker(Closure $resolver) { static::$maker = $resolver; } protected function setCurrentPage(int $currentPage): int { if (!$this->simple && $currentPage > $this->lastPage) { return $this->lastPage > 0 ? $this->lastPage : 1; } return $currentPage; } protected function url(int $page): string { if ($page <= 0) { $page = 1; } if (strpos($this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/'], '[PAGE]https://blog.csdn.net/qq_45764833/article/details/') === false) { $parameters = [$this->options['var_pagehttps://blog.csdn.net/qq_45764833/article/details/'] => $page]; $path = $this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/']; } else { $parameters = []; $path = str_replace('[PAGE]https://blog.csdn.net/qq_45764833/article/details/', $page, $this->options['pathhttps://blog.csdn.net/qq_45764833/article/details/']); } if (count($this->options['queryhttps://blog.csdn.net/qq_45764833/article/details/']) > 0) { $parameters = array_merge($this->options['queryhttps://blog.csdn.net/qq_45764833/article/details/'], $parameters); } $url = $path; if (!empty($parameters)) { $url .= '?https://blog.csdn.net/qq_45764833/article/details/' . http_build_query($parameters, 'https://blog.csdn.net/qq_45764833/article/details/', '&https://blog.csdn.net/qq_45764833/article/details/'); } return $url . $this->buildFragment(); } public static function getCurrentPage(string $varPage = 'pagehttps://blog.csdn.net/qq_45764833/article/details/', int $default = 1): int { if (isset(static::$currentPageResolver)) { return call_user_func(static::$currentPageResolver, $varPage); } return $default; } public static function currentPageResolver(Closure $resolver) { static::$currentPageResolver = $resolver; } public static function getCurrentPath($default = '/https://blog.csdn.net/qq_45764833/article/details/'): string { if (isset(static::$currentPathResolver)) { return call_user_func(static::$currentPathResolver); } return $default; } public static function currentPathResolver(Closure $resolver) { static::$currentPathResolver = $resolver; } public function total(): int { if ($this->simple) { throw new DomainException('not support totalhttps://blog.csdn.net/qq_45764833/article/details/'); } return $this->total; } public function listRows(): int { return $this->listRows; } public function currentPage(): int { return $this->currentPage; } public function lastPage(): int { if ($this->simple) { throw new DomainException('not support lasthttps://blog.csdn.net/qq_45764833/article/details/'); } return $this->lastPage; } public function hasPages(): bool { return !(1 == $this->currentPage && !$this->hasMore); } public function getUrlRange(int $start, int $end): array { $urls = []; for ($page = $start; $page <= $end; $page++) { $urls[$page] = $this->url($page); } return $urls; } public function fragment(string $fragment = null) { $this->options['fragmenthttps://blog.csdn.net/qq_45764833/article/details/'] = $fragment; return $this; } public function appends(array $append) { foreach ($append as $k => $v) { if ($k !== $this->options['var_pagehttps://blog.csdn.net/qq_45764833/article/details/']) { $this->options['queryhttps://blog.csdn.net/qq_45764833/article/details/'][$k] = $v; } } return $this; } protected function buildFragment(): string { return $this->options['fragmenthttps://blog.csdn.net/qq_45764833/article/details/'] ? '#https://blog.csdn.net/qq_45764833/article/details/' . $this->options['fragmenthttps://blog.csdn.net/qq_45764833/article/details/'] : 'https://blog.csdn.net/qq_45764833/article/details/'; } abstract public function render(); public function items() { return $this->items->all(); } public function getCollection() { return $this->items; } public function isEmpty(): bool { return $this->items->isEmpty(); } public function each(callable $callback) { foreach ($this->items as $key => $item) { $result = $callback($item, $key); if (false === $result) { break; } elseif (!is_object($item)) { $this->items[$key] = $result; } } return $this; } public function getIterator() { return new ArrayIterator($this->items->all()); } public function offsetExists($offset) { return $this->items->offsetExists($offset); } public function offsetGet($offset) { return $this->items->offsetGet($offset); } public function offsetSet($offset, $value) { $this->items->offsetSet($offset, $value); } public function offsetUnset($offset) { $this->items->offsetUnset($offset); } public function count(): int { return $this->items->count(); } public function __toString() { return (string) $this->render(); } public function toArray(): array { try { $total = $this->total(); } catch (DomainException $e) { $total = null; } return [ 'totalhttps://blog.csdn.net/qq_45764833/article/details/' => $total, 'per_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->listRows(), 'current_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->currentPage(), 'last_pagehttps://blog.csdn.net/qq_45764833/article/details/' => $this->lastPage, 'datahttps://blog.csdn.net/qq_45764833/article/details/' => $this->items->toArray(), ]; } public function jsonSerialize() { return $this->toArray(); } public function __call($name, $arguments) { $result = call_user_func_array([$this->items, $name], $arguments); if ($result instanceof Collection) { $this->items = $result; return $this; } return $result; }}
第一次发csdn文章,有点激动,简单写两句话记录一下。
以前我都是看别人的文章,没想到自己也勇敢迈出这步
我改进了读别人文章的痛点,就是有时候找不到自己想要的结果在哪。我是上来就把结论给了,对于那些应急的读者很友好,如果想继续深入了解的,则可以继续读下去。
你会问什么场景下会只用到Paginator 类处理好的数据:
在前端只需要提供“第几页”和“每页多少条数据”这两个参数的情况下,利用tp自带的Paginator 类帮我们处理好返回的数据(一般最重要的数据就是参数"data"里包含的当前页的数据,前台直接拿来放到表格就行),而不需要我们自己在后端写复杂的分页逻辑。
例如我现在的项目用tp6+ layui,layui的分页模块laypage只提供“第几页”和“每页多少条数据”这两个参数,分页逻辑要后台写。我从网上找了tp分页逻辑代码,写的都挺乱,也挺多了,所以就想着利用tp自带的Paginator 。Paginator 既然能成功的将分页渲染到模板,那他里面肯定写好了处理分页的逻辑,不用白不用。
上段读完你可能会有一个疑问,Paginator 如何接收“第几页”和“每页多少条数据”这两个参数?
// list_rows传入“每页多少条数据”, page传入“第几页”$list = Db::name('userhttps://blog.csdn.net/qq_45764833/article/details/')->where('statushttps://blog.csdn.net/qq_45764833/article/details/',1)->paginate([ 'list_rowshttps://blog.csdn.net/qq_45764833/article/details/'=> “每页多少条数据”, 'pagehttps://blog.csdn.net/qq_45764833/article/details/' => “第几页”, ]);
最后的最后,感谢你观看。想和我一起探讨tp+html+css+js+jquery+layui相关问题的,欢迎加我qq:1853172620。我也是刚工作的菜鸟,愿我们一起共同进步。
来源地址:https://blog.csdn.net/qq_45764833/article/details/129043310