PHP分页查询实现教程:MySQL LIMIT、总页数计算与前端展示

分页查询是 PHP 后台和内容列表里非常常见的功能。文章列表、商品列表、订单记录、用户管理、日志查询,只要数据量变大,就不能一次性全部查出来,而应该按页加载。

PHP 配合 MySQL 实现分页,核心是根据当前页和每页数量计算偏移量,再使用 LIMIT 查询当前页数据,同时查询总条数计算总页数。本文从基础公式讲起,再整理参数校验、SQL 写法和前端展示思路。

分页核心参数

分页通常需要三个核心参数:当前页 page、每页数量 pageSize、总条数 total。有了这些,就能计算总页数和偏移量。

$page = 1;
$pageSize = 10;
$offset = ($page - 1) * $pageSize;

第一页偏移量是 0,第二页偏移量是 10,第三页偏移量是 20。这个公式是分页查询的基础。

接收页码参数

页码通常来自 GET 参数。读取后要转换为整数,并限制最小值。

$page = max(1, (int)($_GET['page'] ?? 1));
$pageSize = 10;
$offset = ($page - 1) * $pageSize;

不要直接把用户传入的 page 拼进 SQL。即使是数字,也应该转换和限制,避免异常参数影响查询。

PHP分页查询教程配图:MySQL LIMIT 与前端分页展示
分页查询要同时返回当前页数据和分页信息,前端才能正确展示页码。

限制每页数量

如果允许用户指定每页数量,一定要设置上限。否则有人传一个很大的 pageSize,可能导致数据库压力过大。

$pageSize = (int)($_GET['pageSize'] ?? 10);
$pageSize = min(max($pageSize, 1), 100);

这表示每页数量最小 1,最大 100。后台管理系统和公开接口都应该做这种限制。

查询总条数

分页通常需要先查询符合条件的总条数。

$stmt = $pdo->prepare('SELECT COUNT(*) FROM articles WHERE status = ?');
$stmt->execute(['published']);
$total = (int)$stmt->fetchColumn();

总条数用于计算总页数,也能让前端展示“共多少条数据”。如果查询条件很多,总数查询要和列表查询保持一致。

计算总页数

总页数可以使用 ceil() 向上取整。

$totalPages = (int)ceil($total / $pageSize);

如果总条数为 0,总页数可以返回 0,也可以按业务返回 1。前后端要统一约定。

LIMIT 查询

查询当前页数据时使用 LIMIT 和偏移量。

$stmt = $pdo->prepare(
  'SELECT id, title, created_at FROM articles WHERE status = ? ORDER BY id DESC LIMIT ? OFFSET ?'
);

$stmt->bindValue(1, 'published', PDO::PARAM_STR);
$stmt->bindValue(2, $pageSize, PDO::PARAM_INT);
$stmt->bindValue(3, $offset, PDO::PARAM_INT);
$stmt->execute();

$items = $stmt->fetchAll();

绑定 LIMIT 和 OFFSET 时建议使用整数类型。不同数据库和 PDO 配置下,直接 execute 数组传参可能会把数字当字符串处理。

返回 JSON 结构

接口返回分页数据时,建议把列表和分页信息分开。

echo json_encode([
  'items' => $items,
  'pagination' => [
    'page' => $page,
    'pageSize' => $pageSize,
    'total' => $total,
    'totalPages' => $totalPages
  ]
], JSON_UNESCAPED_UNICODE);

结构稳定后,前端分页组件就能复用,不必每个接口单独适配。

前端页码展示

前端展示分页时,通常需要当前页、总页数、上一页、下一页和页码列表。当前页为 1 时禁用上一页,当前页等于总页数时禁用下一页。

const canPrev = page > 1;
const canNext = page < totalPages;

页码很多时,不建议一次显示所有页码,可以显示当前页附近几页,再用省略号表示中间部分。

搜索条件分页

分页经常和搜索条件一起使用。点击下一页时,要保留原来的搜索关键词、分类、状态等参数。

/articles.php?keyword=php&status=published&page=2

后端查询总数和列表时,都要使用同样的筛选条件,否则前端会看到页数和实际数据对不上。

深分页问题

当 page 很大时,LIMIT offset, size 会越来越慢,因为数据库需要跳过大量记录。比如偏移 100000 行,性能可能明显下降。

对于数据量很大的场景,可以考虑游标分页,也就是根据上一页最后一条记录的 ID 或时间继续查询。

SELECT * FROM articles WHERE id < ? ORDER BY id DESC LIMIT 10

游标分页不适合跳到任意页,但适合信息流、日志列表、加载更多等场景。

排序稳定性

分页查询一定要有稳定排序。不要在没有 ORDER BY 的情况下分页,否则不同请求返回顺序可能不一致。

ORDER BY created_at DESC, id DESC

如果创建时间可能重复,可以加上 ID 作为第二排序字段,让顺序更稳定。

常见错误

第一种错误是 page 不做最小值限制,导致 offset 为负数。第二种错误是 pageSize 不设上限。第三种错误是总数查询和列表查询条件不一致。第四种错误是分页没有稳定排序。第五种错误是深分页性能问题被忽略。

实践建议

PHP 分页查询可以按这个流程实现:读取并校验 page 和 pageSize,计算 offset,查询 total,计算 totalPages,使用 LIMIT 查询当前页,返回 items 和 pagination。数据量很大时,再考虑游标分页优化。

分页看似简单,但它关系到性能、接口结构和前端体验。把参数校验、总数计算、排序和返回结构做好,分页功能才会稳定。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容