thinkphp 6 分页需替换驱动而非修改模板,自定义驱动须实现 paginatorrenderinterface 并在 config/paginate.php 中配置 driver 和 drivers 映射;url 参数重复问题需在 render() 中手动处理 query 替换。

ThinkPHP 6 的 Paginator 默认 HTML 结构不能直接改,得换驱动
ThinkPHP 6 的分页类 Paginator 默认使用 Bootstrap 风格的 HTML(带 nav、ul、li),但它的渲染逻辑硬编码在 think\pagination\driver\Bootstrap 里。你改模板文件或继承重写 render() 很容易失效——因为底层驱动会先生成结构,再交由视图处理,而很多样式依赖的是 HTML 标签层级和 class 名。
真正可控的方式是替换分页驱动,让 Paginator 实例用你自己的驱动类来生成 HTML。
- 驱动类必须实现
think\contract\PaginatorRenderInterface - 需在配置中通过
paginate.driver指定新驱动名(如custom) - 驱动类的
render()方法返回纯 HTML 字符串,完全自主控制标签、class、文字
如何注册自定义分页驱动:修改 config/paginate.php 和新增驱动类
ThinkPHP 6 不支持运行时动态注册分页驱动,必须提前在配置里声明。常见错误是只写了类、没配 driver,结果还是走默认 Bootstrap。
- 在
app/common/Paginator/CustomDriver.php中新建驱动类,必须 实现PaginatorRenderInterface接口 - 在
config/paginate.php中添加:'driver' => 'custom',并补充驱动映射:'drivers' => ['custom' => \app\common\Paginator\CustomDriver::class] - 确保类命名空间与
use声明一致,否则报Class not found - 不要试图在控制器里用
new Paginator(...)->setDriver(...)—— 这个方法不存在,Paginator构造后 driver 就已锁定
CustomDriver::render() 里怎么输出无 class 的干净分页 HTML
很多前端框架(比如 Tailwind、UnoCSS 或自研组件)不依赖 Bootstrap class,需要极简结构。这时别拼接字符串,用 sprintf 或模板片段更安全,避免 XSS 和闭合错误。
示例(输出纯 a 标签 + 当前页 span):
public function render(): string
{
if ($this->hasPages() === false) {
return '';
}
$html = '<div class="pagination">';
if ($this->onFirstPage()) {
$html .= '<span class="disabled">«</span>';
} else {
$html .= sprintf('<a href="%s">«</a>', $this->url(1));
}
foreach ($this->elements() as $element) {
if (is_string($element)) {
$html .= sprintf('<span class="dots">%s</span>', $element);
} elseif (is_array($element)) {
foreach ($element as $page => $url) {
if ($page == $this->currentPage()) {
$html .= sprintf('<span class="current">%d</span>', $page);
} else {
$html .= sprintf('<a href="%s">%d</a>', $url, $page);
}
}
}
}
if ($this->hasMorePages()) {
$html .= sprintf('<a href="%s">»</a>', $this->url($this->lastPage()));
} else {
$html .= '<span class="disabled">»</span>';
}
$html .= '</div>';
return $html;
}
分页链接参数冲突:URL 中已有 page 时 $this->url() 会重复拼接
Paginator 的 url() 方法默认把 page 当作查询参数追加,但如果当前 URL 已含 ?page=3&sort=name,调用 $this->url(5) 会生成 ?page=3&sort=name&page=5 —— 多数 Web 服务器只取第一个 page,导致跳转失败。
- 解决办法:在自定义驱动中重写
url()逻辑,用parse_url()+http_build_query()手动替换 query 参数 - 或者更稳妥:在分页查询前统一清理 URL,例如控制器中用
Url::build(request()->url(), ['page' => '__PAGE__'])预留占位,再在驱动里str_replace('__PAGE__', $page, $base) - 注意
request()->url()返回的是带域名的完整 URL,而Paginator默认只处理 path + query,混用易出错
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











