PageFilter 是按请求隔离筛选上下文的设计模式,通过 Request 封装参数、URL 传递、队列显式传参及临时缓存键确保并发下日期筛选不交叉污染。

在 Laravel 并发请求报表页面时,直接使用全局或共享的日期筛选状态(比如 Session、Cache 或静态变量)容易引发数据错乱——例如用户 A 筛选“2024-05-01”,用户 B 同时筛选“2024-05-10”,结果两人看到彼此的日期范围。PageFilter 不是 Laravel 原生组件,而是一种**按请求隔离筛选上下文的设计模式**,核心是把筛选参数绑定到当前 HTTP 请求生命周期内,避免跨请求污染。
用 Request 对象封装筛选参数
不依赖 Session 或全局变量,而是将日期范围作为请求输入显式传递并校验:
- 在控制器方法中直接接收
start_date和end_date,通过 Form Request 自动验证格式与逻辑(如 end_date ≥ start_date) - 将校验后的日期传入报表服务类,确保每次查询都基于本次请求参数构建 SQL WHERE 条件
- 示例:
public function index(ReportFilterRequest $request) { $dates = $request->validated(); $data = $this->reportService->fetchByDateRange($dates['start_date'], $dates['end_date']); return view('reports.index', compact('data', 'dates')); }
前端保持筛选状态不依赖后端存储
避免用 AJAX 更新 Session 来“记住”日期,改用 URL 参数 + 前端同步:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
- 所有筛选操作走 GET 请求,日期参数体现在 URL 中(如
/reports?start_date=2024-05-01&end_date=2024-05-10) - 表单提交设为
method="GET",配合 Laravel 的old()辅助函数回填输入框值 - 用 JavaScript 监听日期控件变化,自动更新 URL(History API),实现无刷新筛选,同时支持浏览器前进/后退
异步导出时单独处理日期上下文
并发导出报表时,若用队列任务,必须把当前请求的日期参数序列化传入,不能在队列中读取 Session 或 Request:
- 在控制器中 dispatch 任务时,显式传入
start_date和end_date - 队列任务构造函数中保存这些值,并在
handle()中用于查询,确保脱离原始请求后仍准确 - 错误做法:在队列中调用
session('filter_dates')—— Session 在队列进程中不可用且不安全
必要时用临时缓存键隔离并发查询
当报表需多次分步查询(如汇总+明细+图表),又需复用同一组日期参数,可生成唯一缓存键,但仅限当前请求生命周期:
- 在中间件或控制器开头生成一次 request_id(如 md5(microtime() . random_int(1,999)))
- 将日期参数存入 Cache,以
"filter_{$request_id}"为键,TTL 设为 300 秒 - 后续子查询通过该 request_id 获取参数,避免重复传参;请求结束即失效,不跨用户、不跨请求

















