SESSION适合存储用户主动选择的分页状态(如page、per_page),避免GET参数丢失或URL膨胀,但需精准管理存取时机、键名前缀及清理逻辑,不可滥用。

为什么不能直接用 $_GET 传分页参数
用户点击第5页后刷新,或从其他页面返回,$_GET['page'] 就丢了;更麻烦的是,如果分页逻辑嵌在搜索结果里,$_GET 还得同时携带关键词、排序、筛选等一堆参数,URL 膨胀且易被篡改。SESSION 能把当前分页上下文“粘”在用户会话里,不依赖 URL,适合需要稳定状态的后台列表或带条件的分页场景。
- 只对当前用户生效,不影响其他人
- 避免敏感参数(如
limit、offset)暴露在 URL 中 - 配合搜索表单时,可让「翻页」自动继承上次的查询条件
- 注意:SESSION 有大小限制(默认 4KB),别往里塞大数组或原始数据集
怎么用 SESSION 存 page 和 per_page
不是所有分页参数都该进 SESSION —— 只存「用户主动选择」的状态,比如当前页码和每页条数;而总记录数、SQL 查询结果这些必须每次重新获取。典型写法是:用户提交搜索或切换 per_page 时,显式写入 SESSION;翻页链接则只传 page,其他靠 SESSION 补全。
// 用户提交搜索表单时保存
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['keyword'])) {
$_SESSION['search_keyword'] = trim($_POST['keyword']);
$_SESSION['page'] = 1; // 新搜索从第1页开始
$_SESSION['per_page'] = (int)($_POST['per_page'] ?? 10);
}
// 翻页时只读取 page 参数,其他靠 SESSION
$page = isset($_GET['page']) ? (int)$_GET['page'] : ($_SESSION['page'] ?? 1);
$per_page = $_SESSION['per_page'] ?? 10;
$offset = ($page - 1) * $per_page;
-
$_SESSION['page']必须在跳转前更新,比如点击「下一页」后,在处理请求时设为$_SESSION['page'] = $next_page - 不要在分页链接里拼
?page=2&per_page=20后还覆盖 SESSION,否则用户手动改 URL 会导致 SESSION 和实际页码错位 - 建议加校验:
$page = max(1, min($page, $total_pages)),防越界
清 SESSION 分页状态的时机很关键
用户点「重置筛选」或进入全新模块时,不清理 SESSION 里的分页参数,就会出现「明明搜了新词,却显示上一个搜索的第8页」这种诡异行为。清理不是全删 $_SESSION,而是精准 unset 相关键。
- 退出登录时,SESSION 自动销毁,无需额外操作
- 执行新搜索前,unset
$_SESSION['page']、$_SESSION['search_*等相关键 - 如果用了多个独立分页(如订单页 + 用户页),给 SESSION 键加前缀:
$_SESSION['order_page']、$_SESSION['user_page'],避免互相污染 - 调试时可用
var_dump($_SESSION)确认哪些键残留了
和 Laravel / ThinkPHP 等框架的 SESSION 分页冲突吗
框架自带的分页器(如 Laravel 的 paginate())默认只读 $_GET['page'],不会自动从 SESSION 取值。想混用,得自己封装一层:把框架分页器的 appends() 替换成从 SESSION 读参,再手动构造 LengthAwarePaginator 实例。但多数情况下没必要 —— 框架分页本身已解决 URL 状态保持,强行套 SESSION 反而增加复杂度和维护成本。
立即学习“PHP免费学习笔记(深入)”;
- 纯原生 PHP 项目用 SESSION 管理分页状态是合理选择
- 框架项目优先走框架约定,除非有强需求(如禁用 GET 参数、SEO 隐藏分页)
- 若真要结合,重点不是存 page,而是确保
render()生成的链接不带多余参数,且能回写 SESSION
SESSION 存分页状态本身很简单,难的是判断「什么时候该存」「什么时候该删」「和其他参数怎么协同」—— 这些边界没理清,反而会让分页行为变得不可预测。











