ThinkPHP 6 分页需用 field(['id','title','create_time']) 显式指定字段并确保包含主键,再调用 paginate();剔除元信息用 items() 获取纯数据,配合 currentPage()、hasMore() 等方法定制响应;TP5.1 不支持链式 field(),须用 Db 查询或闭包传参。

ThinkPHP 6 分页结果中只返回指定字段(如 id、title、create_time)
默认 paginate() 会返回完整模型对象,包含所有字段甚至关联属性,既浪费带宽又暴露敏感数据。要控制输出字段,不能靠 field() 直接链在 paginate() 前——它对分页器内部的查询无效。
正确做法是:先用 field() 构建查询,再调用 paginate(),且必须确保 field() 在 where() 等条件之前或之后都生效(TP6 中顺序不影响)。
-
field()必须显式列出需要的字段,不支持field('id,title,create_time')这种字符串写法(虽能运行但易出错),推荐数组形式:field(['id', 'title', 'create_time']) - 主键字段(如
id)必须包含,否则分页器可能无法正常计算总数或生成链接 - 如果用了软删除(
useSoftDelete),delete_time字段会被自动加进查询,若不想返回,需在field()中明确排除,但注意不能漏掉主键 - 关联模型字段不能通过主模型的
field()控制,需单独处理关联查询或改用withField()(TP6.1+)
$list = Article::field(['id', 'title', 'create_time', 'status'])
->where('status', 1)
->order('create_time DESC')
->paginate(10);
ThinkPHP 6 分页响应中剔除 total、per_page 等元信息
TP6 默认分页响应结构包含 data、last_page、total 等字段。若只需纯列表数据 + 当前页码,可调用 items() 获取原始数据数组,再手动包装。
注意:items() 返回的是当前页的数据集合(已应用 field()),不带分页元信息,也不含 render() 所需的分页对象方法。
- 不要用
toArray()直接转分页对象——它仍会保留大量元数据 - 若还需
current_page或has_more,建议用->currentPage()、->hasMore()等方法单独取值 - 避免对
items()结果再调用hidden()或visible()——这些是模型方法,items()返回的是数组,不是模型实例
$page = Article::field(['id', 'title'])->paginate(10);
$data = [
'list' => $page->items(),
'page' => $page->currentPage(),
'has_more' => $page->hasMore()
];
ThinkPHP 5.1 分页字段控制与 TP6 的关键差异
TP5.1 的 paginate() 不接受 field() 链式调用影响结果字段,必须改用闭包方式传入查询对象,否则 field() 会被忽略。
这是最常踩的坑:代码看起来一样,但在 TP5.1 中 field() 写在 paginate() 前完全无效。
- TP5.1 正确写法是:
paginate(10, false, ['query' => request()->param()])配合Db::name('article')->field('id,title')->where(...)->paginate() - TP5.1 中模型的
field()对分页无效,必须用 Db 查询或重写baseQuery() - TP5.1 没有
items()方法,要用all()或直接取$page->toArray()['data'],但后者仍含冗余字段 - TP5.1 的分页对象不支持
hasMore(),得靠$page->lastPage() > $page->currentPage()判断
自定义分页响应结构时,count 查询被重复执行的问题
当你在分页后手动调用 count() 或对结果做二次处理(比如合并关联数据),TP6 可能因缓存未命中而重新执行 count 查询,导致 SQL 多跑一次。
根本原因是分页器内部的 count 查询未复用,尤其在你修改了查询条件或使用了子查询时更明显。
- 避免在
paginate()后再调用count()——用$page->total()直接取已算好的总数 - 若需自定义 count 逻辑(如按用户权限过滤统计),应使用
paginate(10, false, ['total' => $customCount])显式传入 - 开启查询日志(
'log_sql' => true)可快速验证是否出现重复 count 查询 - TP6.2+ 支持
withTotal()方法预设总数,比手动传total更安全
字段精简和结构定制本身不难,难的是在不同版本间保持行为一致,以及在去掉冗余的同时,不意外丢掉分页器依赖的关键字段(比如主键或排序依据)。稍不注意,render() 就会报错或分页链接失效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











