thinkphp 6.x 必须用 paginate() 实现分页,因其自动执行 count 和 limit 查询并封装为带 render() 等方法的 paginator 对象;手动 limit/offset 或自定义函数无法处理 url 参数、页码解析、总条数统计及链接生成,将导致 render() 报错或功能缺失。

ThinkPHP 6.x 中不能直接用自定义翻页函数替代 paginate()
ThinkPHP 的分页逻辑深度耦合在查询构建器和 paginator 组件中,直接写个 my_page() 函数并传入原始数组或 SQL 结果,无法自动处理 URL 参数、当前页码解析、总条数统计、分页跳转链接生成等——这些不是“调用函数”能绕开的。你真正需要的,是让自定义逻辑融入 TP 的分页生命周期,而不是替换它。
如何把自定义分页样式/逻辑注入到 paginate() 渲染过程
TP 6 默认使用 think\paginator\driver\Bootstrap(或其他驱动),但它的模板和渲染行为可被覆盖。关键不是重写分页函数,而是接管渲染环节:
- 在
config/paginate.php中修改'type'配置,指向你自己的分页类,比如'type' => app\util\MyPaginator::class - 你的
MyPaginator类继承think\Paginator,重写render()方法,控制 HTML 输出结构(如去掉 Bootstrap 标签、加图标、改 class 名) - 若需改变数据获取逻辑(例如用 Redis 缓存总条数),不要动
render(),而应在调用paginate()前手动设置:$query->withTotalCount(false)->paginate(15),再自行补上$paginator->total = $cachedCount
为什么不要自己封装 array_chunk() + 手动算 offset/limit
这种做法在 TP 环境下极易出错:
- URL 中的
page参数不会被自动识别,input('page')要自己取、校验、默认值处理 -
lengthAwarePaginator依赖的总记录数必须精确,而SELECT COUNT(*)若没走索引或表大,会拖慢首屏;但用SQL_CALC_FOUND_ROWS在 TP 里不被原生支持,需手动写原生查询 - 分页链接(如上一页 / 下一页 / 跳转 form)全部得手写生成,且要兼容路由模式(pathinfo / rewrite)、参数保留(如带
?status=1) - TP 的
paginate()返回对象有appends()、currentPage()、hasPages()等方法,自定义数组分页后这些能力全丢失
真要扩展功能?优先用 setConfig() 和视图替换
大多数所谓“自定义翻页”,其实只是改样式或加字段,完全不必碰底层逻辑:
- 在控制器中调用时加配置:
$list->setConfig(['prev_text' => '‹', 'next_text' => '›', 'theme' => '%FIRST% %UP_PAGE% %LINKS% %DOWN_PAGE% %END% %TOTAL_ROW% %HEADER%']) - 复制 TP 源码里的
vendor/topthink/think-orm/src/paginator/driver/bootstrap.php模板到view/paginate/下,重命名为my.php,然后在配置里设'view' => 'paginate/my' - 如果需要异步加载分页(如点击加载更多),保持
paginate()后端逻辑不变,只在前端用 JS 拦截链接、发 AJAX、替换内容区域——此时后端仍返回标准think\Paginator实例,render()可照常输出隐藏的分页 HTML 供 JS 提取
真正难的从来不是“怎么写个翻页函数”,而是怎么让自定义行为和 TP 的请求生命周期、URL 生成、模板引擎、缓存策略对齐。一旦脱离这个链路,补丁越打越多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











