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

Laravel文件驱动缓存:通过键片段匹配查询缓存值的方法

在Laravel文件驱动缓存中实现按键片段匹配查找

嘿,我完全懂你想实现的需求——就像SQL里用like '%{segment}%'那样,通过缓存键的片段找到对应的缓存值,而且你现在用的是文件驱动。刚好我之前也遇到过类似的场景,给你分享两个可行的方案:

方案一:直接遍历缓存文件解析(适合小缓存量)

Laravel的文件驱动缓存,每个缓存项都存在storage/framework/cache/data目录下的独立文件里。虽然文件名是缓存键的哈希值,但文件内容里会保存原始的缓存键、序列化后的值和过期时间,格式是{原始键}|{序列化值}|{过期时间}。我们可以遍历这些文件,解析出原始键进行匹配:

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;

function findCacheByKeySegment(string $segment): array
{
    // 获取文件缓存的存储实例和目录路径
    $store = Cache::store('file')->getStore();
    $cacheDir = $store->getDirectory();
    
    $matchingItems = [];
    
    // 遍历目录下所有缓存文件
    foreach (File::allFiles($cacheDir) as $file) {
        $content = File::get($file);
        // 按|分割内容,提取原始缓存键
        $parts = explode('|', $content, 3);
        
        if (count($parts) < 2) {
            continue; // 跳过格式异常的文件
        }
        
        $cacheKey = $parts[0];
        // 检查键是否包含目标片段
        if (str_contains($cacheKey, $segment)) {
            // 反序列化获取缓存值
            $value = unserialize($parts[1]);
            $matchingItems[$cacheKey] = $value;
        }
    }
    
    return $matchingItems;
}

优缺点

  • ✅ 不需要额外配置或修改现有代码,直接可用
  • ❌ 缓存文件较多时,遍历解析会很慢,性能差,只适合缓存量小的场景

方案二:维护缓存键索引(适合大缓存量)

如果你的缓存项比较多,遍历文件的方式就不太高效了。这时候可以提前维护一个缓存键的索引集合,把所有缓存键存在一个固定的缓存项里,查找时先从索引里筛选匹配的键,再批量获取对应的值。

方式1:手动维护索引(简单直接)

在设置缓存的时候,同步更新索引:

use Illuminate\Support\Facades\Cache;

// 封装带索引的缓存设置方法
function setCacheWithIndex(string $key, $value, $ttl = null)
{
    Cache::put($key, $value, $ttl);
    
    // 更新索引:把新键加入索引数组
    $index = Cache::get('cache_keys_index', []);
    if (!in_array($key, $index)) {
        $index[] = $key;
        // 索引可以设为永久有效,或者比所有缓存项的过期时间更长
        Cache::forever('cache_keys_index', $index);
    }
}

// 根据片段查找缓存
function findCacheByKeySegment(string $segment): array
{
    $index = Cache::get('cache_keys_index', []);
    // 筛选包含目标片段的键
    $matchingKeys = array_filter($index, fn($key) => str_contains($key, $segment));
    
    // 批量获取缓存值,比逐个获取更高效
    return Cache::many($matchingKeys);
}

方式2:用缓存事件自动维护索引(更优雅)

手动修改所有设置缓存的地方太麻烦?可以利用Laravel的缓存事件,自动在缓存键被写入或删除时更新索引:

  1. 注册事件监听器
    在app/Providers/EventServiceProvider.php里添加监听:
protected $listen = [
    \Illuminate\Cache\Events\KeyWritten::class => [
        \App\Listeners\UpdateCacheKeyIndex::class,
    ],
    \Illuminate\Cache\Events\KeyDeleted::class => [
        \App\Listeners\RemoveCacheKeyFromIndex::class,
    ],
];
  1. 创建写入事件监听器
    生成UpdateCacheKeyIndex类:
namespace App\Listeners;

use Illuminate\Cache\Events\KeyWritten;
use Illuminate\Support\Facades\Cache;

class UpdateCacheKeyIndex
{
    public function handle(KeyWritten $event)
    {
        $index = Cache::get('cache_keys_index', []);
        if (!in_array($event->key, $index)) {
            $index[] = $event->key;
            Cache::forever('cache_keys_index', $index);
        }
    }
}
  1. 创建删除事件监听器
    生成RemoveCacheKeyFromIndex类:
namespace App\Listeners;

use Illuminate\Cache\Events\KeyDeleted;
use Illuminate\Support\Facades\Cache;

class RemoveCacheKeyFromIndex
{
    public function handle(KeyDeleted $event)
    {
        $index = Cache::get('cache_keys_index', []);
        if (($position = array_search($event->key, $index)) !== false) {
            unset($index[$position]);
            // 重新索引数组,避免空键
            Cache::forever('cache_keys_index', array_values($index));
        }
    }
}

这样不管是用Cache::put()、Cache::forever()还是其他方法设置缓存,索引都会自动更新,删除缓存时也会同步移除索引里的键,完全不用手动干预。

优缺点

  • ✅ 查找速度极快,适合缓存量大的场景
  • ✅ 自动维护索引后,无需修改现有业务代码
  • ❌ 需要额外维护索引,会占用一点缓存空间

总结

如果你的缓存项数量不多,方案一的遍历方式足够简单好用;如果缓存量较大,推荐用方案二的索引方式,性能提升很明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:40:03