错误原因是将数组当作查询对象调用paginate(),正确做法是在未执行查询前调用,如$model->where()->paginate();对已处理数组需用Paginator::make($items, $total, $per_page, $current_page)。

ThinkPHP 分页报错:Call to a member function paginate() on array
这是最常遇到的错误,本质是把普通数组当成了查询构造器对象来调用 paginate()。ThinkPHP 的分页必须基于 Query 或 Builder 对象(比如 Db::table()、$model->where() 返回的),不能直接对 array 或 Collection 调用。
常见场景:查完数据手动处理(如合并、过滤、排序)后试图分页;或用了 select() 立即执行,返回的是二维数组而非延迟查询对象。
- ✅ 正确做法:分页必须在「未执行查询」前调用,例如
$model->where(...)->paginate(10)或Db::name('user')->where(...)->paginate(10) - ❌ 错误写法:
$list = $model->select(); $list->paginate(10)——$list是数组,没有paginate方法 - ⚠️ 注意:即使你用
collection($data)->paginate(),TP 原生也不支持;得换方案(见下一条)
想对已有数组分页?用 think\facade\Paginator::make()
如果你的数据已经查出来、加工好了(比如 API 聚合多个来源、缓存反序列化、Excel 导入后内存数组),就不能走模型/查询器分页,得手动构造分页实例。
Paginator::make() 是唯一官方支持的「数组分页」入口,但它不自动算总条数,需你显式传入 total 参数,否则页码逻辑会错乱。
立即学习“PHP免费学习笔记(深入)”;
- 必须提供三个参数:
$items(当前页数据数组)、$total(真实总数)、$per_page(每页几条) - 第四个参数
$current_page通常从input('page')拿,不传会默认为 1 - 示例:
Paginator::make($processedArray, $totalCount, 15, input('page', 1)) - ⚠️ 容易漏:
$total不能用count($processedArray)代替——那是当前页数量,不是全量总数
paginate() 的 $simple 参数设 true 后,为什么 getLinks() 报错?
开启简单分页(paginate(10, true))会返回 LengthAwarePaginator 的简化版(其实是 SimplePagination 实例),它没有 getLinks() 方法,只有 render() 和基础遍历能力。
这个设计是为了减少 COUNT 查询提升性能,但代价是丢弃了「总页数」「跳转链接生成」等依赖总数的功能。
- ✅ 用
render()直接输出 HTML 分页控件(Laravel 风格模板兼容) - ❌ 别调
$page->getLinks()或$page->lastPage()—— 这些方法在简单分页里不存在 - ? 如果你需要自定义分页 HTML 又想省 COUNT,就自己算:
ceil($total / $per_page),但$total得你额外提供 - ⚠️ 兼容性注意:TP6.0+ 的
SimplePagination不再继承完整 Paginator,方法表大幅缩减
自定义分页 URL 参数时,page 参数被忽略或重复拼接
默认情况下 paginate() 生成的链接用 page 作为页码键,但如果你启用了路由变量、或者用了 withQueryString(),很容易导致 page 出现在 URL 两次,或被其他参数覆盖。
典型表现:点第 2 页,URL 变成 ?page=2&page=1,后一个生效,始终卡在第 1 页。
- 推荐显式控制:用
appends()手动追加除page外的参数,避免全量透传 - 示例:
$list->appends(request()->except('page')),比withQueryString()更可控 - 如果用了路径参数(如
user/index/page/2),确保分页生成器知道用路径方式渲染:setPath(url('user/index')) - ⚠️ 尤其注意中间件或全局请求过滤修改了
$_GET,可能导致input('page')读错值
分页看着简单,但一旦混入数组处理、URL 重写、缓存、多数据源聚合,问题就藏在「谁负责算总数」「谁决定当前页」「谁生成链接」这三件事的职责边界上。边界模糊了,报错就只是时间问题。



















