ThinkPHP 6 自定义分页需继承 Bootstrap 类重写 render() 方法,显式指定 type 参数;支持跳转页码和每页条数切换需手动拼接带 query 的 URL;AJAX 分页须判断 isAjax() 并返回纯 HTML 片段。

ThinkPHP 6 的 paginate() 默认样式怎么替换
默认分页 HTML 是硬编码在 think\paginator\driver\Bootstrap 类里的,直接改源码等于埋雷——下次升级就丢。真正可维护的做法是继承并重写渲染模板。
实操建议:
- 新建类
app\util\CustomPaginator,继承think\paginator\driver\Bootstrap - 重写
render()方法,返回你自己的 HTML 字符串(注意保留$this->app->config->get('pagination')中的var_page、list_rows等关键参数) - 在分页调用处显式指定驱动:
UserModel::paginate(15, false, ['page' => input('page/d', 1), 'query' => request()->param(), 'type' => \app\util\CustomPaginator::class])
常见错误:只覆盖了 render() 却没处理 hasMore() 或 currentPage() 的逻辑,导致“下一页”按钮在最后一页仍显示。
如何让 ThinkPHP 分页支持「跳转到指定页」+「每页条数切换」
原生 paginate() 不提供前端交互所需的表单结构和路由参数透传机制,必须手动拼接 url() 并确保 query 参数不丢失。
立即学习“PHP免费学习笔记(深入)”;
实操建议:
- 在模板中用
url('index', array_merge(request()->param(), ['page' => 1]))生成首页链接,避免清空搜索条件 - 「跳转页码」输入框需配合 JS 提交表单,且 form action 必须带完整 query 参数(例如
?keyword=abc&page=),否则提交后丢失筛选条件 - 「每页条数」切换建议用 GET 链接而非表单,例如:
<a href="<?= url('index', array_merge(request()->param(), ['list_rows' => 20])) ?>">20条/页</a>
容易踩的坑:把 list_rows 当作分页器内部参数硬编码,实际它只是查询时的 limit 值;分页对象本身不感知这个值,需在控制器中手动传递给 paginate() 的第二个参数(即每页数量)。
自定义 Pagination 扩展类里怎么安全获取当前 URL 参数
request()->param() 会包含所有 GET + POST 参数,但分页只需要保留非分页相关的查询条件(比如搜索词、分类 ID),否则 page 和 list_rows 会被重复携带,造成链接混乱。
实操建议:
- 用
array_diff_key(request()->param(), array_flip(['page', 'list_rows']))过滤掉分页专用键 - 更稳妥的方式是显式声明白名单:
$keep = ['keyword', 'category_id', 'status']; $query = array_intersect_key(request()->param(), array_flip($keep)) - 注意:如果用了路由变量(如
route('user/detail', ['id' => 123])),则不能依赖request()->param(),得从Route::current()->params()取
性能影响小,但兼容性差在 TP6.0.0 ~ 6.0.8 之间 request()->param() 对空数组处理不一致,建议加 ?? [] 防错。
为什么扩展 Pagination 后 AJAX 分页总失败
核心原因:AJAX 请求时,request()->isAjax() 为 true,但分页模板里仍输出完整 HTML 布局(含 <html><body>),浏览器解析失败。
实操建议:
- 在自定义
render()开头加判断:if ($this->app->request->isAjax()) { return $this->renderAjax(); } -
renderAjax()只返回纯分页 HTML 片段(如<div class="pagination">...</div>),不包含任何 layout 或 script 标签 - 前端 JS 接收响应后,用
document.querySelector('.pagination').innerHTML = data替换,不要用location.reload()
最容易被忽略的是:TP 默认关闭了 AJAX 请求的 CSRF token 自动注入,如果分页链接含 POST 表单(如跳转页码),需手动在 JS 中读取 meta 标签或 hidden input 的 token 值并附带到请求头。



















