You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 7 中间件缓存无法命中:始终返回X-Proxy-Cache: MISS

解决Laravel 7中间件缓存中Cache::has()始终返回false的问题

根据你描述的情况——缓存文件确实存在但Cache::has($key)返回false,且执行dd()时缓存文件被自动删除,我梳理了几个最可能的原因及对应的解决方案:

1. 缓存已过期,Laravel自动清理过期条目

你在路由中设置的缓存TTL是5(即5分钟),如果测试时缓存已经超过有效期,Laravel的文件缓存驱动会自动判定缓存失效,返回false并删除过期的缓存文件。

解决方案:

  • 临时将TTL改大(比如cacheable:1440,即24小时),重新生成缓存后立即测试,确认是否是过期问题。
  • 查看缓存文件的内容,Laravel的文件缓存会在内容开头存储过期时间戳,你可以通过这个判断缓存是否还在有效期内。

2. 缓存内容格式不匹配,反序列化失败

你提到打开缓存文件能看到目标页面内容,但根据你的代码,存储的是数组['content' => $response->content()],正常情况下Laravel会对这个数组进行PHP序列化,缓存文件内容应该是类似a:1:{s:7:"content";s:XXX:"页面HTML内容";}的格式,而非纯HTML。

如果缓存文件是纯HTML,说明这是旧缓存(比如你之前的代码直接存储响应字符串而非数组),当Laravel尝试反序列化纯HTML时会失败,进而删除该缓存文件并返回false。

解决方案:

  • 删除storage/framework/cache/data目录下的所有缓存文件,清空旧缓存后重新生成。
  • 可以简化缓存逻辑,直接存储响应字符串而非数组,避免序列化/反序列化问题:
    // 修改存储逻辑
    if(!empty($response->content())) Cache::put($key, $response->content(), $ttl);
    
    // 修改读取逻辑
    if(Cache::has($key)){
        $cache = Cache::get($key);
        $response = response($cache);
        $response->header('X-Proxy-Cache', 'HIT');
    }
    

3. 缓存键生成不一致

虽然你用了相同的逻辑生成缓存键,但可能存在请求参数处理的细微差异(比如某些参数的大小写、空值处理),导致存储和读取时的$key不一致。

解决方案:

  • 在中间件中添加日志输出,确认存储和读取时的缓存键完全相同:
    use Illuminate\Support\Facades\Log;
    
    // 生成key后添加日志
    $key = md5(url()->current().'?'.http_build_query($params));
    Log::info('当前缓存键: ' . $key);
    
  • 查看storage/logs/laravel.log,对比缓存存储和读取时的键是否一致。

4. 缓存驱动配置异常

检查config/cache.php的配置,确保:

  • default选项设置为file(你当前用的是文件缓存)
  • stores.file.path指向正确的路径:storage/framework/cache/data
  • prefix配置没有特殊字符或冲突(不过你用md5生成key,冲突概率极低)

5. 调试缓存文件的实际路径

可以直接验证Laravel是否能找到对应的缓存文件,添加以下代码到中间件中:

use Illuminate\Cache\FileStore;
use Illuminate\Filesystem\Filesystem;

// ...

$key = md5(url()->current().'?'.http_build_query($params));
// 获取Laravel实际查找的缓存文件路径
$store = new FileStore(new Filesystem(), storage_path('framework/cache/data'));
$cacheFilePath = $store->path($key);
Log::info('缓存文件路径: ' . $cacheFilePath);
Log::info('文件是否存在: ' . file_exists($cacheFilePath));

如果文件存在但Cache::has($key)返回false,基本可以确定是反序列化或过期时间的问题。

内容的提问来源于stack exchange,提问作者AlexB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 08:22:31