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

Laravel中如何按前缀批量清除File驱动的缓存项?

问题

我希望移除所有键以自定义字符串开头的缓存项。目前我为Permission模型创建了PermissionObserver,通过自定义Trait ObserverEvent来调用handle方法,代码如下:

class PermissionObserver
{
    use ObserverEvent;

    private function handle(Permission $permission)
    {
        $emails = User::pluck('email');
        foreach ($emails as $email) {
            $key  = 'permission_index_'. $email;
           if (cache()->has($key)) {
                cache()->forget($key);
           }
        }

        $ids = User::pluck('id');
        foreach ($ids as $id) {
            $key1  = 'permission_create_users_'. $id;
            $key2  = 'permission_edit__users_'. $id;
            if (cache()->has($key1)) {
                 cache()->forget($key1);
            }
            if (cache()->has($key2)) {
                cache()->forget($key2);
            }
        }

        // It will continue like this....

        logger()->build(CUSTOM_BUILD_LOG_CHANNEL)->info("PERMISSION_CACHE_CLEARED");
    }
}

现在这段代码越来越冗长,还出现了性能问题,且其他模型也存在类似逻辑。

补充说明:我未使用redis、database、dynamodb、memcached或octane缓存驱动,使用的是默认的file存储驱动,请问是否有办法清除所有键以permission开头的缓存,实现类似cache()->forget('permission*')(该写法无效)的效果?


解决方案

由于Laravel的file缓存驱动不支持通配符删除,我们可以通过遍历缓存文件、匹配缓存键前缀的方式实现批量删除:

1. 封装通用批量删除方法

在项目中创建一个全局辅助函数或缓存工具类,实现按前缀删除缓存的逻辑:

use Illuminate\Support\Facades\Cache;
use Illuminate\Cache\FileStore;

function deleteCacheByPrefix(string $prefix): void
{
    $store = Cache::store();

    // 仅针对file驱动执行逻辑
    if (!$store instanceof FileStore) {
        return;
    }

    $cacheDirectory = $store->getDirectory();
    $files = scandir($cacheDirectory);

    foreach ($files as $file) {
        $filePath = $cacheDirectory . DIRECTORY_SEPARATOR . $file;

        // 跳过目录和非PHP缓存文件
        if (is_dir($filePath) || !str_ends_with($file, '.php')) {
            continue;
        }

        $content = file_get_contents($filePath);
        // 匹配Laravel file缓存中的键字段格式
        if (preg_match('/"key";s:\d+:"(.*?)"/', $content, $matches)) {
            $cacheKey = $matches[1];
            if (str_starts_with($cacheKey, $prefix)) {
                // 调用Laravel的forget方法删除,会自动处理缓存过期等逻辑
                Cache::forget($cacheKey);
                // 也可以直接删除文件:unlink($filePath);
            }
        }
    }
}

2. 简化Observer代码

修改PermissionObserver的handle方法,直接调用封装好的方法即可:

private function handle(Permission $permission)
{
    deleteCacheByPrefix('permission_');
    
    logger()->build(CUSTOM_BUILD_LOG_CHANNEL)->info("PERMISSION_CACHE_CLEARED");
}

3. 注意事项

  • 若缓存文件数量极大,遍历操作可能会有短暂性能消耗,建议在低峰期执行,或定期清理缓存目录。
  • 该方法可复用至其他模型的Observer,只需传入对应缓存键前缀即可,避免重复编写冗长的遍历逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:15:40