php分页逻辑必须在控制器中完整计算并传入smarty,严禁模板处理;需传$page、$limit、$total、$offset等关键参数,url翻页链接须继承所有业务查询参数,sql的where和limit/offset必须严格一致。

PHP分页逻辑必须在控制器里算清,不能甩给Smarty
Smarty不处理分页计算,只负责渲染。你传什么,它就输出什么;漏传关键参数,页码就直接崩掉。最常见错误是只传 $page 和 $limit,却忘了 $total——没有总记录数,模板根本没法算出总页数,$pages = ceil($total / $limit) 就会失效。
必须明确传入的变量:
-
$page:当前页码,建议从 1 开始(别用 0 起始,否则 URL 和逻辑易混乱) -
$limit:每页几条,要和 SQL 的LIMIT严格一致 -
$total:数据库查出的真实总条数(不是count(*)估算值,而是带 where 条件后的准确值) -
$offset:直接用于 SQL 的偏移量,$offset = ($page - 1) * $limit,避免模板里重复计算
额外推荐传入:$pages(总页数)、$pager(预组装好的页码数组),能大幅降低模板复杂度。
URL参数必须手动继承,否则翻页就丢搜索条件
翻页链接不是简单写 page=2,而是要把当前所有有效查询参数(比如 keyword=php、cid=5、sort=name)都带上。否则点“下一页”,关键词没了,分类没了,结果全错。
PHP 端生成分页链接时,建议用 http_build_query() 拼接:
$params = $_GET; $params['page'] = $i; // 替换 page 值 $url = '?' . http_build_query($params);
注意过滤掉可能干扰的键(如 PHPSESSID 或调试参数),但业务参数一个都不能少。
别在Smarty模板里写页码循环逻辑
Smarty 的数学函数($smarty.section.xxx.index、math 插件)又慢又难 debug,还容易因数据结构变化崩掉。更稳妥的做法是:PHP 层直接生成好 $pager 数组,再 assign('pager', $pager) 进去。
例如 PHP 端构造一个带结构的页码数组:
$pager = [];
for ($i = 1; $i $base_url . '&page=' . $i,
'num' => $i,
'is_current' => ($i == $page),
'is_ellipsis' => false
];
}
// 再加前后省略逻辑(如 1, 2, ..., 8, 9, 10)
$smarty->assign('pager', $pager);
模板里就干净了:
{foreach $pager as $p}
{if $p.is_ellipsis}
<span class="dots">…</span>
{else}
<a href="https://www.php.cn/link/b7af411bc561c0025f74b5e2c6e233bc" class="{if $p.is_current}active{/if}">{$p.num}</a>
{/if}
{/foreach}
SQL查询和分页变量必须严格对齐
很多人写完分页逻辑,SQL 却没配好:要么 LIMIT $limit OFFSET $offset 没用上,要么 $offset 算错(比如用了 $page * $limit 而不是 ($page - 1) * $limit),导致第一页多一条、最后一页空着。
检查点:
- 查总数的 SQL 和查数据的 SQL,WHERE 条件必须完全一致
-
$limit和$offset必须用整型传入 PDO/MySQLi,防止注入或类型转换错误 - 如果用了缓存,确保
$total和分页数据来自同一缓存 key,否则总数和实际列表对不上
最隐蔽的坑是:当 $page 超过 $pages 时,不要静默返回空数组,而应重定向到合法页码或返回 404——否则用户看到空白页,还以为系统挂了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











