ThinkPHP5.1中paginate()必须在模型上调用,返回Paginator对象需用items()获取数据、render()输出分页HTML;URL参数需通过query选项保留;field/with可能导致总数不准,应优先优化查询而非手动分页。

ThinkPHP5.1中paginate()必须在模型/查询构造器上调用
直接在控制器里写$list = Db::table('user')->paginate(10)能跑,但不推荐——它绕过了模型层,丢失自动时间戳、软删除、事件等能力。正确做法是用模型,比如UserModel::where('status', 1)->paginate(10)。注意:paginate()返回的是Paginator对象,不是数组,不能直接foreach,必须用$list->items()取数据,否则模板里会报错。
前端模板里用$list->render()输出分页HTML,别手写for循环
TP5.1默认用Bootstrap风格渲染,{$list->render()}会自动拼出带链接的页码条。常见错误是试图用{volist name="list" id="vo"}直接遍历$list,结果只显示第一页——因为$list本身是分页对象,要遍历的是$list->items()。模板里应这样写:
{volist name="list.items" id="vo"}
<p>{$vo.name}</p>
{/volist}
{$list->render()}
如果项目没引入Bootstrap CSS,分页样式会乱,但链接仍可用;可自定义主题,改配置'page' => ['type' => 'bootstrap']为'simple'或继承think\Paginator重写render()。
立即学习“PHP免费学习笔记(深入)”;
URL参数不保留导致翻页后搜索条件丢失
比如首页带关键词搜索:/index/index/index?keyword=php,点第二页变成/index/index/index?page=2,keyword没了。解决方法是在paginate()调用时传['query' => request()->param()]:
$list = UserModel::where('name', 'like', '%'.$keyword.'%')
->paginate(10, false, ['query' => request()->param()]);
这样生成的分页链接会自动带上keyword=php。注意request()->param()包含所有GET/POST参数,如只需保留特定几个,手动构造数组,例如['query' => ['keyword' => $keyword]]。
分页总数不准?检查是否用了field()或with()关联查询
当调用field('id,name')后接paginate(),TP5.1可能因COUNT(*)和SELECT字段不一致导致SQL错误或总数为0;用with('profile')时,如果关联表有WHERE条件但主表没加distinct,也可能重复计数。稳妥做法是显式指定分页总数:
- 先查总数:
$total = UserModel::where(...)->count() - 再查数据:
$list = UserModel::where(...)->limit($offset, $pageSize)->select() - 最后手动构建分页对象:
new \think\Paginator($list, $pageSize, $page, $total, [...])
不过这属于“退化用法”,多数场景下优先排查field和with的使用方式,避免过早手动分页。



















