总页数计算错误的根本原因是未用ceil()向上取整、每页条数非正整数或删/查后未重算总数;必须三者兼顾:$total_pages = (int)ceil($total_count / $per_page),$per_page ≥ 1,每次操作后按相同WHERE条件重查COUNT(*)并校验$page ≥ 1。

总页数算错,根本原因是用了错误的数学方法或没处理边界情况。最稳妥的做法是:用 ceil() 除法、确保每页条数为正整数、每次查询前重新统计总数——三者缺一不可。
总页数必须用 ceil(),不能用 round() 或 int
比如总记录 23 条、每页 10 条,正确总页数是 3(23 ÷ 10 = 2.3 → 向上取整得 3)。若用 (int)(23/10) 得 2,第 3 页就永远无法显示;用 round(23/10) 在 25 条时会得 2(25/10=2.5 → 四舍五入为 2),漏掉最后 5 条。
- ✅ 正确写法:
$total_pages = (int)ceil($total_count / $per_page); - ❌ 避免:
(int)($total_count / $per_page)、round($total_count / $per_page)、floor() - 注意:
$per_page为 0 或负数时,PHP 会警告或结果异常,需提前校验:$per_page = max(1, (int)$_GET['per_page'] ?? 10);
删数据后不重算总数,页码就“悬空”
用户刚删了 15 条记录,但分页仍按旧总数算页码,导致请求 ?page=5 时查不到数据,页面空白。这不是前端按钮禁用能解决的,必须服务端兜底。
- 执行删除操作后,立刻用
COUNT(*)重新查一次过滤条件下的真实总数 - 再算最大合法页码:
$max_page = $total_count > 0 ? (int)ceil($total_count / $per_page) : 1; - 如果当前
$_GET['page'] > $max_page,直接 302 跳转到$max_page(或首页) - 别复用缓存的总数——尤其在高并发下,删完不刷新,页码错乱概率极高
过滤条件变了,但总页数还按全表算
带分类筛选、搜索关键词、状态过滤的列表,常见错误是:COUNT 总数用的是无 WHERE 的全表统计,而实际数据查询加了 WHERE。结果总数虚高,页码多出几页,点进去全是空。
立即学习“PHP免费学习笔记(深入)”;
- 总数 SQL 和分页数据 SQL 必须共用完全相同的
WHERE条件 - 例如筛选
status = 1 AND category_id = 5,COUNT 也得写:SELECT COUNT(*) FROM table WHERE status = 1 AND category_id = 5 - ThinkPHP 中用
paginate()时,确保模型查询链已完整添加 where,不要在 paginate 之后补条件 - 若用原生 SQL,两个查询语句的条件字符串建议抽成变量复用,避免手误
传参非法导致 page 值崩坏,连带总数计算失效
$_GET['page'] 是字符串,未强转就参与计算,会导致 $page = '3abc' 变成 3(还好),但 'abc3' 变成 0,'-5' 变成 -5——offset 成负数,MySQL 直接报错,后续的总数计算甚至不会执行。
- 统一入口校验:
$page = max(1, (int)($_GET['page'] ?? 1)); - 更安全可用:
$page = filter_input(INPUT_GET, 'page', FILTER_SANITIZE_NUMBER_INT); $page = max(1, (int)$page); - 数据库查询前先做这步,否则后面所有逻辑(包括总数判断、OFFSET 计算、页码导航生成)都建立在错误基础上



















