thinkphp 5.0+ 应直接使用 paginate() 方法实现分页,无需手写 page 类;需显式传入 query 参数保留搜索条件;自定义分页样式应继承 paginator 重写 render() 和 getlinks();模板中须用 {$list|raw} 或 {$page} 输出 html。

直接用 paginate() 就能分页,别手写 Page 类
ThinkPHP 5.0+ 默认推荐用模型或查询构造器的 paginate() 方法,不是老版本的 Page 类。它自动处理总数统计、SQL LIMIT、当前页计算和 URL 生成,一行代码搞定基础分页。
常见错误是手动 new Page 并拼 limit,不仅冗余,还容易漏传 query 参数导致搜索条件丢失。
-
Db::name('user')->where('status', 1)->paginate(10)—— 最简写法,每页 10 条 -
UserModel::where('status', 1)->paginate(['list_rows' => 8, 'page' => input('page', 1)])—— 显式控制页码和条数 - 必须把
query参数传进去,否则翻页时搜索关键词会丢:'query' => request()->param()
render() 输出的 HTML 不符合 UI?别改 vendor,注册自定义分页类
默认输出的是 Bootstrap 风格的 <ul class="pagination"></ul>,如果你用的是 Layui、AmazeUI 或纯自定义结构,硬改 vendor/thinkphp/library/think/paginator/driver/Bootstrap.php 是错的——Composer 更新后立刻被覆盖。
正确做法是新建一个分页驱动类,继承 think\Paginator,重写 render() 和 getLinks()(后者控制显示哪些页码数字)。
- 类文件放
app/paginator/driver/Layui.php,命名空间对应为app\paginator\driver - 配置中写
'type' => 'Layui'即可生效,TP 会自动加载 - 不要只重写
render():TP6 的getLinks()内部调用getUrlRange(),不重写它,页码范围逻辑还是走默认的“当前页 ±2”
分页链接带搜索参数失败?query 必须显式传,不能靠默认行为
很多人以为只要 URL 里有 ?keyword=abc&page=2,下一页按钮就会自动带上 keyword,其实不会。TP 默认只保留 var_page(如 page),其他参数需手动注入。
典型错误写法:paginate(10) —— 这样翻页链接只有 /list?page=3,搜索条件全丢。
- 正确传法:
paginate(10, false, ['query' => request()->param()]) - 如果只传部分参数,比如只留
keyword和category:'query' => ['keyword' => input('keyword'), 'category' => input('category')] - 注意:request()->param() 包含所有 GET/POST 参数,如果表单用了 POST 提交搜索,得单独取 GET 参数,否则翻页时 POST 数据无法透传
样式改完页面没变化?检查模板里是不是用了 {$list->render()} 而不是 {$page}
很多人在控制器 assign 了 $page = $list->render(),模板里却写 {$list->render()},结果每次渲染都重新执行一次分页逻辑,可能触发重复查询或报错;或者更糟:直接 echo $list 对象,输出的是 JSON 字符串而非 HTML。
还有人用 {:$list->render()}(冒号语法),这会自动调用 htmlspecialchars,把 <a></a> 标签转义成纯文本,分页变一串乱码。
- 安全且标准的写法是:
{$list|raw}—— 禁用自动转义,输出原始 HTML - 如果用了
assign('page', $list->render()),模板里就写{$page},别再调render() - 调试时可用
{:dump($list->toArray())}看结构,但上线前删掉
getLinks() 方法的重写——它决定了“是否显示首页/尾页”“中间显示几个数字”,而这个逻辑完全不在 render() 里。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











