tp5 paginate如何实现自动分页?
in 后端 with 0 comment

tp5 paginate如何实现自动分页?

in 后端 with 0 comment

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

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

//这里是传递了$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的代码

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')的值。

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。

    /**
     * 自动获取当前页码
     * @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()方法实现自动分页。

Comments are closed.