php分页核心是手动计算limit offset, length,其中offset = ($page - 1) * $per_page,须严格校验$page为正整数、$per_page白名单限制,sql必须带order by和一致where条件,大数据量应改用游标分页。

PHP分页功能不是调用一个函数就能完事,核心是手动算出 LIMIT 和 OFFSET,再配合严格校验与正确 SQL 结构才能稳定运行。直接拼接用户输入、漏掉 ORDER BY、用错 LIMIT 参数顺序,都会导致数据错乱或性能崩溃。
怎么写对 LIMIT 和 OFFSET 的 SQL 语句
MySQL 的 LIMIT 必须带两个参数:LIMIT offset, length,不是 LIMIT length OFFSET offset(后者虽能执行,但易读性差,且和 PostgreSQL 混淆)。常见错误是把第 2 页写成 LIMIT 2, 10,实际应为 LIMIT 10, 10(跳过前 10 条,取 10 条)。
-
OFFSET= ($page- 1) ×$per_page,$page必须 ≥ 1,否则OFFSET为负数,MySQL 会报语法错误 - 必须显式写
ORDER BY,否则分页结果无序,同一页可能重复或丢失记录 - 排序字段(如
id或created_at)最好有索引,否则OFFSET越大越慢 - 示例正确写法:
SELECT id, title FROM article ORDER BY id DESC LIMIT 20, 10
为什么不能直接用 $_GET['page'] 拼进 SQL
因为 $_GET['page'] 是字符串,可能被注入恶意内容,比如 ?page=1; DROP TABLE users--;即使看起来像数字,也可能含空格、符号或超大值(如 9999999999),导致 OFFSET 溢出或查询超时。
- 必须用
(int)$_GET['page']或filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT)强制转整型 - 转完后还要校验范围:
$page = max(1, min($page, $total_pages)),防止请求第 1000 页而数据库只有 50 条 -
$per_page不能由用户自由传入,建议硬编码(如10)或白名单限制(如只允许[10, 20, 50]) - PDO 预处理不支持
LIMIT ?单占位符,OFFSET和LIMIT参数必须先转整型再拼入 SQL 字符串
查总数和查数据的 WHERE 条件必须完全一致
很多人分开写两条 SQL:一条 COUNT(*),一条带 LIMIT 的主查询,但 WHERE 条件稍有差异(比如一个写了 status = 1,另一个漏了),就会导致总页数和实际可翻页数对不上——翻到最后一页突然空白,或某页数据重复。
- 把公共条件抽成变量,例如
$where = "WHERE status = ? AND category_id = ?",两边都复用 - 统计总数用:
SELECT COUNT(*) FROM table $where - 查数据用:
SELECT * FROM table $where ORDER BY id DESC LIMIT ?, ? - 别用
SQL_CALC_FOUND_ROWS:MySQL 8.0+ 已弃用,且在高并发下性能比单独COUNT(*)还差
大数据量下 OFFSET 会变慢,什么时候该换游标分页
当表记录超过 10 万、用户频繁翻到第 50 页以后,OFFSET 499990 就意味着 MySQL 要扫描并丢弃近 50 万行,响应明显变慢甚至超时。这时不能再靠页码,得改用基于唯一有序字段的游标分页。
- 适用前提:有单调递增/递减的唯一字段(如自增
id、带索引的created_at) - 首次请求:
SELECT * FROM post ORDER BY id DESC LIMIT 11(多查 1 条用于判断是否有下一页) - 拿到第 11 条的
id(比如12345),下一页请求改为:SELECT * FROM post WHERE id - 前端需把上一页末尾的
id值作为参数传回,而不是传page=3 - 注意:游标分页不能跳页(无法直接从第 1 页跳到第 100 页),但“下一页”体验更稳、更快
最容易被忽略的是:页码参数必须参与所有查询逻辑的一致性校验,包括总数统计、主数据查询、前端链接生成——少一处同步,就可能在第 37 页开始漏数据。另外,LIMIT 后的两个数字必须都是整型,PDO 绑定时若没指定 PDO::PARAM_INT,会被当字符串处理,直接报错。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











