tp5 paginate如何实现自动分页?

这次的问题起源于昨天新增接口时 发现的问题

下面是一个老接口的部分源码

1
2
3
4
5
6
7
8
9
10
11
//这里是传递了$page参数 page是前端请求中的$_POST['page']
$data = User::getUserList($page,$limit);

//这里是getUserList
public static function getUserList($page = 1,$limit = 10){
$data = self::name('用户数据表')
->field(字段....)
->order(排序条件...)
->paginate($limit);
return $data->toArray();
}

咦,虽然$page已经传递过去了,但是在getUserList()中却并没有使用到$page,可为什么能返回正确的结果呢?

这时候我们查看paginate的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public function paginate($listRows = null, $simple = false, $config = []) {
if (is_int($simple)) {
$total = $simple;
$simple = false;
}
if (is_array($listRows)) {
$config = array_merge(Config::get('paginate'), $listRows);
$listRows = $config['list_rows'];
} else {
$config = array_merge(Config::get('paginate'), $config);
$listRows = $listRows ?: $config['list_rows'];
}

/** @var Paginator $class */
$class = false !== strpos($config['type'], '\\') ? $config['type'] :
'\\think\\paginator\\driver\\' . ucwords($config['type']);
$page = isset($config['page']) ? (int) $config['page'] :call_user_func([$class,'getCurrentPage'], $config['var_page']);

$page = $page < 1 ? 1 : $page;

$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class,'getCurrentPath']);

if (!isset($total) && !$simple) {
$options = $this->getOptions();

unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);

$bind = $this->bind;
$total = $this->count();
$results = $this->options($options)->bind($bind)->page($page,$listRows)->select();
} elseif ($simple) {
$results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
$total = null;
} else {
$results = $this->page($page, $listRows)->select();
}
return $class::make($results, $listRows, $page, $total, $simple,$config);
}

我们并没有传递$simple,$listRows也是int型,所以直接进入了第10行。断点输出一下Config::get(‘paginate’)的值。

1
2
3
4
5
6
7
8
array(3) {
["type"]=>
string(9) "bootstrap"
["var_page"]=>
string(4) "page"
["list_rows"]=>
int(15)
}

10,11行分别读取了paginate的配置和设置了分页量,继续看。

12行设置了使用 \think\paginator\driver\bootstrap 来实现分页

13行开始设置$page,也就是我们想要追寻的问题: $page是怎么来的。因为$config中没有键名为page的键,所以执行了\think\paginator\driver\bootstrap::getCurrentPage(),传递了$config[‘var_page’]。

也就是执行了 \think\paginator\driver\bootstrap::getCurrentPage(‘page’);

现在来看看这个getCurrentPage方法。在bootstrap中没有找到这个方法,但是bootstrap继承了think\Paginator类,点开think\Paginator。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 自动获取当前页码
* @param string $varPage
* @param int $default
* @return int
*/
public static function getCurrentPage($varPage = 'page', $default = 1)
{
$page = (int) Request::instance()->param($varPage);

if (filter_var($page, FILTER_VALIDATE_INT) !== false && $page >= 1) {
return $page;
}

return $default;
}

嗯哼,找到了。执行了Request::instance()->param(‘page’)来获取$page,而Request::instance()->param(‘page’)是获取当前请求参数中(包含GET|POST|PUT|DELETE)名称为 page 的参数值

也就是说 只要在请求中 带上一个名为page参数,在后端就可以使用paginate()方法实现自动分页。


评论区