ThinkPHP 5.1.41 分页不生效主因是分页对象被toArray()/all()解包、模板未用{:widget('think\paginator\driver\Bootstrap', $list)}或{$list->render|raw}渲染、query未透传搜索参数、或深分页SQL无索引导致超时。

分页不生效在 ThinkPHP 5.1.41 中,通常不是框架“坏了”,而是几个关键环节没对齐:分页对象被意外解包、模板渲染方式错误、查询条件未透传、或底层 SQL 没走索引导致超时假象。下面直接说清楚怎么一步步排查和解决。
分页变量被转成数组,render() 报错或不显示
常见于控制器里写了 ->toArray()、->all() 或用 foreach 遍历后重新赋值。
比如:
$list = Article::where('status', 1)->paginate(10)->toArray(); // ❌ 错误!
$this->assign('list', $list);这样 $list 就是纯数组,没了 render()、lastPage() 等方法。
✅ 正确做法是保持分页对象原样传递:
$list = Article::where('status', 1)->paginate(10); // ✅ 不加任何转换
$this->assign('list', $list);模板中用:
{:widget('think\paginator\driver\Bootstrap', $list)} <!-- TP5.1 默认渲染方式 -->
<!-- 或 -->
{$list->render|raw}分页链接点击后总跳回第一页(归档页/带参数页特别明显)
原因是 paginate() 默认只认 page 参数,其他如 ?year=2024&cat=tech 不会自动带入分页 URL。
✅ 必须显式通过 query 参数透传:
$year = input('year/d', 0);
$where = [];
if ($year) {
$where['publish_time'] = ['between', [$year.'-01-01', $year.'-12-31']];
}
$list = Article::where($where)
->order('publish_time desc')
->paginate([
'list_rows' => 15,
'query' => ['year' => $year], // ← 关键!让下一页链接带上 year=2024
]);如果有多参数,用 array_filter(request()->param()) 过滤空值再传:
'query' => array_filter(request()->param())
分页极慢甚至超时,疑似“不生效”(实际是卡死)
TP5.1 默认 paginate() 会执行两条 SQL:COUNT(*) + SELECT ... LIMIT。数据过万后,LIMIT 9990, 20 会导致 MySQL 扫描前 9990 行,页面卡住像“没反应”。
✅ 三步快速缓解:
- 关掉总数统计(跳过
COUNT(*)):$list = Db::name('article')->where('status', 1)->paginate(20, false); - 模板改用简单分页(不依赖总页数):
{$list->simple()->appends(request()->param())->render|raw} - 给查询字段加复合索引,例如
WHERE status=1 ORDER BY publish_time DESC,建:ALTER TABLE `article` ADD INDEX idx_status_ptime (status, publish_time DESC);
extend 扩展类加载失败,间接影响分页组件
TP5.1.41 存在一个已知问题:若项目根目录下没有 think 文件(比如把 index.php 放到了根目录,又删了 think),会导致 Loader 加载异常,分页驱动(如 Bootstrap)类找不到。
✅ 解决方案二选一:
- 在项目根目录新建一个空文件
think(内容为空即可); - 或恢复原始目录结构:
index.php放public/下,think文件保留在根目录。
基本上就这些。重点不在“装没装上”,而在于对象是否完整、参数是否透传、SQL 是否高效、环境是否合规。
立即学习“PHP免费学习笔记(深入)”;



















