如何实现基于最后 ID 的双向分页(上一页/下一页)

发布时间 - 2025-12-29 00:00:00    点击率:

本文介绍一种不依赖连续 id 的 mysql 双向分页方案:通过记录边界 id 并结合 `array_reverse()` 实现稳定、高效、容错的上一页/下一页导航,完美解决因数据删除导致 id 不连续带来的翻页错乱问题。

在基于 ID 的分页实践中,常见的“游标分页”(Cursor-based Pagination)通常采用 WHERE id 上一页却容易陷入误区:若简单使用 WHERE id 当前页起始 ID 为下界进行反向查询。

✅ 正确思路是:

  • 下一页:WHERE id
  • 上一页:WHERE id > $first_id LIMIT 21 → 获取更大 ID 的数据(自然升序),再反转数组,使其视觉顺序与用户预期一致(即顶部显示 ID=99,底部显示 ID=120)。

以下是完整 PHP + MySQL 实现示例(含关键注释):

prepare("SELECT * FROM table_name WHERE id > ? LIMIT ?");
    $stmt->execute([$_GET['prev'], $limit]);
    $results = array_reverse($stmt->fetchAll(PDO::FETCH_ASSOC));
} elseif ($isNext) {
    // 下一页:查比 $last_id 更小的 21 条(降序)
    $stmt = $db->prepare("SELECT * FROM table_name WHERE id < ? ORDER BY id DESC LIMIT ?");
    $stmt->execute([$_GET['next'], $limit]);
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
} else {
    // 首页:取最大的 21 条
    $stmt = $db->prepare("SELECT * FROM table_name ORDER BY id DESC LIMIT ?");
    $stmt->execute([$limit]);
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

// 渲染数据(假设按 id 降序展示)
foreach ($results as $row) {
    echo "ID: {$row['id']} | {$row['title']}";
}

// 生成分页按钮(关键:传递正确的边界 ID)
$firstId = !empty($results) ? $results[0]['id'] : null;
$lastId  = !empty($results) ? end($results)['id'] : null;

// 上一页按钮:传当前页第一条记录的 ID(即上一页的「最小 ID」应 > 它)
if ($firstId !== null) {
    echo '← 上一页';
}

// 下一页按钮:传当前页最后一条记录的 ID(即下一页的「最大 ID」应 < 它)
if ($lastId !== null && count($results) === $limit) {
    echo '下一页 →';
}
?>

⚠️ 重要注意事项

  • 必须确保 id 字段有索引(如主键或唯一索引),否则 WHERE id > ? 查询将全表扫描,性能急剧下降;
  • 避免混合使用 OFFSET:传统 LIMIT offset, size 在大数据量下效率低下,且无法精准支持“上一页”逻辑;
  • 边界 ID 必须来自当前页真实数据:切勿用计算(如 $firstId - 21),因 ID 不连续;
  • 前端需禁用重复提交:防止用户快速点击导致状态错乱;
  • 考虑添加 created_at 辅助排序:若存在同 ID 冲突(极罕见),可加二级排序保障稳定性,如 ORDER BY id DESC, created_at DESC。

该方案彻底摆脱对 ID 连续性的依赖,即使中间大量删除数据,翻页依然精准、响应迅速,是高并发、大数据量场景下的推荐实践。


# mysql  # php  # 前端  # 大数据  # 并发  # 上一页  # 下一页  # 分页  # 升序  # 当前页  # 更大  # 降序  # 翻页  # 不连续  # 使其 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  新三国志曹操传主线渭水交兵攻略  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  Laravel如何创建自定义Artisan命令?(代码示例)  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  Python文件操作最佳实践_稳定性说明【指导】  ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】  做企业网站制作流程,企业网站制作基本流程有哪些?  如何在景安云服务器上绑定域名并配置虚拟主机?  如何快速查询域名建站关键信息?  javascript基于原型链的继承及call和apply函数用法分析  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  如何在IIS中新建站点并配置端口与物理路径?  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  如何快速建站并高效导出源代码?  如何在Windows虚拟主机上快速搭建网站?  如何在服务器上配置二级域名建站?  轻松掌握MySQL函数中的last_insert_id()  Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)  如何登录建站主机?访问步骤全解析  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  如何在七牛云存储上搭建网站并设置自定义域名?  浅析上传头像示例及其注意事项  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  黑客入侵网站服务器的常见手法有哪些?  中山网站制作网页,中山新生登记系统登记流程?  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  Laravel如何实现多对多模型关联?(Eloquent教程)  使用PHP下载CSS文件中的所有图片【几行代码即可实现】  CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】  魔方云NAT建站如何实现端口转发?  Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制  三星网站视频制作教程下载,三星w23网页如何全屏?  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  phpredis提高消息队列的实时性方法(推荐)  电视网站制作tvbox接口,云海电视怎样自定义添加电视源?  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  javascript日期怎么处理_如何格式化输出  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  如何快速搭建高效简练网站?  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  详解Android图表 MPAndroidChart折线图  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  如何快速搭建高效WAP手机网站?  详解阿里云nginx服务器多站点的配置  javascript读取文本节点方法小结