php怎么实现分页功能_php数据库分页查询代码【经典】

12次阅读

mysql limit 的 offset 是偏移量而非页码,正确计算为 ($page-1)*$size;offset 过大导致性能骤降;并发下易重复或遗漏,宜用游标分页;php 中须(int) 强转并校验范围,防 sql 注入与越界。

php 怎么实现分页功能_php 数据库分页查询代码【经典】

MySQL LIMIT 用法和 offset 容易错在哪

分页的核心就是 LIMIT,但它不是“取第几页”,而是“跳过 N 条后取 M 条”。很多人写成 LIMIT $page, $size,结果第一页就崩——因为 MySQL 的 LIMIT offset, length 第一个参数是偏移量,不是页码。

  • 页码从 1 开始,但 offset = ($page - 1) * $size 才对;写成 $page * $size 会每页少查一条
  • offset 过大时(比如几百万行后),MySQL 仍要扫描前面所有行,性能断崖式下降
  • 如果数据有并发增删,靠 OFFSET 分页会出现重复或遗漏(游标分页更稳,但需有序主键)

PHP 中拼接分页 SQL 的安全写法

直接字符串拼接 $page$size 是 SQL 注入高危操作。哪怕你“确定是数字”,也得走类型强转或 PDO 绑定——因为 PHP 的弱类型可能让 "123abc" 变成 123,但攻击者可以构造 "123 OR 1=1" 绕过判断。

  • 必须用 (int) 强转页码和每页条数:$page = (int)$_GET['page'] ?: 1;$size = min((int)$_GET['size'], 100);(防爆破)
  • SQL 中只允许这两个变量进 LIMIT,且必须放在最后、不参与 WHERE
  • 示例正确写法:$sql = "SELECT id,name FROM user WHERE status=1 ORDER BY id DESC LIMIT " . ($page-1)*$size . ", " . $size;

怎么算总页数才不查两次数据库

很多代码先 SELECT COUNT(*)SELECT …… LIMIT,看似合理,但并发写入时,两次查询之间数据可能变化,导致页码错乱或最后一页空。

  • 如果业务允许“近似总数”,可用 SHOW TABLE STATUS LIKE 'user'Rows 字段(MyISAM 准,InnoDB 是估算)
  • 更靠谱的是用 SQL_CALC_FOUND_ROWS(已弃用,8.0+ 不支持),或改用子查询加 COUNT(*) OVER()(MySQL 8.0+)
  • 实际项目中,多数场景只需“有没有下一页”:查 $size + 1 条,够 $size+1 就显示下一页按钮,否则不显示

前端传参和边界处理的硬坑

用户手动改 URL 里的 page=999999 很常见,不拦住就会查出空结果甚至拖垮数据库。

立即学习PHP 免费学习笔记(深入)”;

  • 页码必须校验范围:if ($page,同时建议设上限(如 <code>max_page = 1000
  • 每页数量也要限制(1),防止 <code>size=10000 把内存打满
  • 不要依赖 $_GET 原值:$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;,否则未传 page(int)null 是 0,offset = -10 直接报错
  • 错误提示别暴露细节,400 Bad Request 比“offset 不能为负”更安全

真正难的不是写出能跑的分页,而是想清楚:这里能不能接受数据轻微偏移?要不要为高偏移量加缓存?游标分页的排序字段有没有唯一性保证?这些比语法细节更容易被忽略。

text=ZqhQzanResources