thinkphp分页靠paginate()自动处理查询与渲染,需直接链式调用而非先select再分页;正确传入query参数可避免翻页丢失搜索条件,模板中用{$list->render()}输出html分页。

ThinkPHP 的分页不是手写 SQL + limit 拼接,而是靠 paginate() 方法自动处理查询和渲染 —— 你只要给它数据源,它就生成分页对象、计算总数、切片数据、还自带 HTML 模板。
怎么调用 paginate() 获取分页数据
最常见场景:控制器里查列表并分页。关键点是不能先 select() 再分页,必须让 paginate() 接管整个查询链:
-
Db::name('user')->where('status', 1)->order('id desc')->paginate(10)✅ 正确:底层会执行两次查询(一次 COUNT,一次 LIMIT) -
Db::name('user')->select()->paginate(10)❌ 错误:select()已把全部数据取回内存,paginate()只是对数组分页,失去数据库层优化 - 如果用模型,写法一样:
UserModel::where('score', '>', 60)->paginate(15)
paginate() 的参数怎么配才不翻车
第二个参数控制是否自动渲染 HTML;第三个参数是配置数组,常改的有:
-
query:追加 URL 参数,比如搜索关键词['keyword' => $keyword],避免翻页后丢失条件 -
page:手动指定当前页码(默认从$_GET['page']读,但 API 场景可能需从 header 或 JSON body 取) -
var_page:自定义页码参数名,如设为'p',URL 就变成?p=2而非?page=2 -
list_rows:每页条数,等价于第一个参数,但放配置里更清晰
示例:UserModel::where('type', 'admin')->paginate(8, false, ['query' => request()->param()]) —— 关闭自动渲染,同时透传所有 GET 参数。
立即学习“PHP免费学习笔记(深入)”;
模板里怎么显示分页 HTML 和读取数据
控制器 assign 后,模板中:
- 数据循环用
{$list}(变量名是你 assign 的),它是当前页的数据集(对象数组或关联数组) - 分页 HTML 直接写
{$list->render()},它会输出带样式的<ul class="pagination"></ul> - 想自定义样式?别改
render()输出,而是用simple()或继承Bootstrap类,或直接遍历$list->render()返回的字符串做替换 - 获取总条数:
{$list->total()};当前页码:{$list->currentPage()};总页数:{$list->lastPage()}
为什么分页跳转后条件丢了?
最常见原因是没传 query 配置。比如带搜索的列表:
$where = [];
if ($keyword = input('keyword/s')) {
$where['name'] = ['like', "%{$keyword}%"];
}
$list = Db::name('article')->where($where)->paginate(10, false, ['query' => ['keyword' => $keyword]]);
$this->assign('list', $list);
漏掉 ['query' => [...]],翻页链接就是 ?page=2,keyword 消失。另外注意:如果用了路由变量(如 route('article/index', ['keyword' => $k])),也要确保 query 里同步带上,否则 render() 生成的链接不含路由参数。
分页本身不难,难的是条件透传和自定义渲染时对 render() 返回结构的误判 —— 它输出的是完整 HTML 片段,不是纯 URL 数组,真要深度定制,得看 think\Paginator 的源码逻辑,而不是硬正则替换。











