分页不生效主因是paginate()调用位置错误或结果被提前解包:必须接在查询构造器(如where、orderBy)后,不可接在all()、find()等已执行查询的方法后;需保持返回值为原始Paginator实例,避免toArray()、json()等操作丢失分页方法;URL参数需显式通过query选项透传。

分页不生效,大概率不是没装对,而是 paginate() 调用位置错了,或者结果被意外“解包”了。
paginate() 必须接在查询构造器之后,不能接在模型静态方法上
常见错误写法:User::all()->paginate(10) 或 User::find(1)->paginate(10),会直接报 Call to undefined method think\Collection::paginate()。
原因:这些静态方法返回的是 Collection 或单个模型实例,已经执行完 SQL 查询,失去构建分页所需上下文(COUNT + LIMIT)。
正确姿势必须从查询构造器开始:
立即学习“PHP免费学习笔记(深入)”;
User::where('status', 1)->paginate(10)Db::name('user')->where('status', 1)->order('id', 'desc')->paginate(10)- 不能是
Db::query(...)原生 SQL 结果,也不支持子查询封装后调用
分页对象被 toArray()、json()、foreach 等操作提前转成数组
现象:控制器里写了 $list = User::paginate(10);,但模板中 {$list->render()} 报错,或 {$list->lastPage()} 不存在。
根本原因:你在赋值或传参前做了任何“遍历”或“转换”,比如:
$list = User::paginate(10)->toArray();-
foreach ($list as $item) { ... }后再传给模板 -
return json($list);—— 这会触发自动序列化,丢失 Paginator 方法
解决办法:保持 $list 是原始 Paginator 实例;模板中渲染必须用 {$list->render|raw}(TP6),且不能对 $list 做任何集合操作。
URL 参数没透传,翻页时搜索条件丢失
现象:带条件查询如 ?keyword=abc&page=1,点“下一页”变成 ?page=2,keyword 消失了。
这是因为默认 render() 只保留 page 参数,其他一律丢弃。
修复方式是在 paginate() 中显式传入 query:
User::paginate(['listRows' => 15, 'query' => request()->param()])- 注意不是
['query' => input()],request()->param()才能拿到全部 GET/POST 参数(不含 page) - 如果用了自定义页码参数名(如
p),要同步排除它:'query' => array_diff_key(request()->param(), ['p' => 0])
配置或环境导致 Paginator 类型异常
某些场景下 paginate() 返回的是 think\Paginator\Simple(无总条数),而不是带 render() 的完整分页器,常见于:
- 数据库配置中开启了
'collection' => true(TP6 默认为false,设为true会强制转 Collection) - 使用了
simplePaginate()而非paginate() - 关联查询中混用了
field()或alias(),触发了隐式降级
验证方法:在控制器里 dump($list),看类名是不是 think\Paginator\Bootstrap 或 think\Paginator\Simple;前者有 render(),后者没有。
最易被忽略的点:分页不是“调一个方法就完事”,它依赖两个 SQL 协同——先 COUNT(*) 算总数,再 LIMIT 取数据。只要中间断了这个链路(比如手动改 SQL、用了子查询、或提前取了数据),分页信息就不可逆地丢了。



















