ThinkPHP分页总页数为1的常见原因是提前调用select()或get()导致分页器失去统计上下文,必须用paginate()直接链式调用查询构造器,如Db::name('user')->where('status',1)->paginate(10)。

ThinkPHP 的分页不是靠手写 SQL LIMIT 拼接,而是用 paginate() 方法自动处理——但直接调用不设置参数,很容易翻到空页或总数不准。
为什么 paginate() 返回的总页数总是 1?
常见原因是没在查询时保留原始条件,尤其用了 where() 后又调用 select(),导致分页器失去统计上下文。
- 必须用
paginate()替代select(),例如:$list = Db::name('user')->where('status', 1)->paginate(10); - 如果用了模型,确保没提前执行
get()或find()——这些会触发立即查询,分页器无法再获取总条数 - 自定义查询(如
Db::query()原生 SQL)不支持paginate(),得手动查总数 + LIMIT 分页
如何在模板里正确渲染分页 HTML?
ThinkPHP 默认返回的分页对象有 render() 方法,但直接输出可能样式错乱,因为默认只生成纯 HTML 标签,不含 CSS。
- 在控制器中把分页对象赋给模板变量:
$this->assign('list', $list); $this->assign('page', $list->render()); - 模板中用
{$page|raw}输出(|raw防止被自动转义) - 若需自定义样式,可传参控制:
$list->render(['type' => 'bootstrap']),但注意 Bootstrap 版本兼容性(v5 不兼容旧版 render) - 不要在模板里对
$list调用toArray()再手工拼分页,会丢失 URL 参数(如 ?page=2)
URL 参数带搜索条件时,分页链接丢失参数怎么办?
默认 paginate() 只保留当前请求的 page,其他 GET 参数(如 ?keyword=abc&status=1)不会自动透传。
立即学习“PHP免费学习笔记(深入)”;
- 用
withQuery()显式携带:paginate(10, false, ['query' => request()->param()]) - 更稳妥的是只传需要的参数:
['query' => ['keyword' => input('keyword'), 'status' => input('status')]] - 注意:如果参数含数组(如复选框多值),
request()->param()会自动处理,但手动构造时得用http_build_query()或确保键名一致
分页看似简单,真正卡住人的往往是「总数统计逻辑」和「URL 参数继承」这两处。前者出问题表现为页码跳变或最后一页空白;后者出问题就是点下一页回到第一页、搜索条件消失——这两个地方不验证一遍,上线后容易被用户反馈“翻不了页”。



















