laravel中间件缓存有五种方式:一、基于url全量响应缓存;二、基于请求特征条件化拦截;三、redis标签管理多维生命周期;四、响应修饰型非终止写入;五、请求参数标准化缓存。

如果您在 Laravel 应用中需要对特定请求路径或条件下的响应进行统一缓存控制,避免重复执行控制器逻辑与数据库查询,则可在中间件层集成缓存逻辑。以下是多种可直接实施的集成方式:
一、基于请求 URL 的全量响应缓存
该方法将整个 HTTP 响应内容序列化后存入缓存,适用于无用户状态依赖、纯静态或低频更新的 GET 接口,能跳过路由分发与控制器执行,显著降低框架开销。
1、执行 php artisan make:middleware CacheResponse 创建中间件类。
2、在 handle() 方法中调用 $request->fullUrl() 生成唯一缓存键,例如 'http:response:'.md5($request->fullUrl())。
3、使用 Cache::get($key) 尝试获取已缓存的响应字符串;若存在,则构造 response($content, 200) 并立即返回。
4、若未命中,调用 $next($request) 执行后续流程,并在响应对象生成后,通过 $response->getContent() 提取原始内容写入缓存,TTL 设为 300 秒。
二、基于请求特征的条件化缓存拦截
该方法允许根据请求头、查询参数、用户身份等运行时特征动态决定是否启用缓存,适用于需区分游客/登录用户、移动端/桌面端、灰度流量等场景,实现细粒度缓存策略。
1、在中间件 handle() 中提取关键特征:如 $request->header('X-Device-Type')、$request->query('locale')、$request->user() ? $request->user()->id : 'guest'。
2、组合生成带上下文的缓存键,例如 'conditional:api:users:list:'.$device.':'.$locale.':'.$userId。
3、仅当满足预设白名单规则(如请求方法为 GET、路径匹配 /api/v1/users、且无 X-No-Cache 头)时才执行缓存读写逻辑。
4、缓存未命中时,继续流程;响应返回前,检查 $response->getStatusCode() === 200 后再写入缓存,防止错误响应被误存。
三、使用 Redis 标签管理多维度缓存生命周期
该方法解决缓存批量失效难题,当某类资源(如用户资料、文章分类)更新时,可精准清除所有关联中间件缓存项,避免全局 flush 导致缓存雪崩。
1、在写入缓存时使用 Cache::tags(['user', 'profile'])->put($key, $content, $ttl),为缓存项打上语义化标签。
2、在模型观察器中监听 User::updated 事件,触发 Cache::tags(['user', 'profile'])->flush()。
3、确保缓存驱动配置为 redis,因 file 和 database 驱动不支持标签功能。
4、在中间件读取时仍使用原键名调用 Cache::get($key),标签仅用于写入与失效,不影响读取性能。
四、响应修饰型缓存写入(非终止式)
该方法不中断请求生命周期,而是在响应即将发送前注入缓存逻辑,适用于需保留中间件链完整执行顺序、或需结合响应头(如 ETag、Last-Modified)协同工作的场景。
1、在中间件 handle() 中不提前返回,而是调用 $next($request) 获取原始响应对象。
2、注册闭包回调至 $response->withHeaders(['X-Cache-Status' => 'MISS']),并使用 $response->sendHeaders() 前的时机点。
3、在 terminate() 方法中判断响应状态码与内容长度,仅对成功响应执行 Cache::put($key, $response->getContent(), $ttl)。
4、关键提示:必须在 terminate() 中完成写入,否则响应已发送至客户端,无法再访问原始内容体。
五、请求参数标准化后缓存
该方法解决因 URL 查询参数顺序不同(如 ?a=1&b=2 与 ?b=2&a=1)导致缓存键不一致的问题,确保语义相同请求复用同一缓存项。
1、在中间件中调用 collect($request->query())->sortKeys()->all() 对查询参数按键字母序归一化。
2、使用 http_build_query() 重建标准查询字符串,再拼入完整 URL 哈希,例如 sha1($request->url().'?'.http_build_query($sortedQuery))。
3、对 POST 请求,若需缓存其响应(如幂等性接口),则使用 json_encode($request->except('_token')) 作为键的一部分。
4、禁止将敏感字段(如 api_token、password)纳入键构造,应在标准化前调用 $request->except(...) 过滤。











