如何在Laravel 5中按键获取所有缓存项目的列表?

时间:2015-08-03 15:28:26

标签: php laravel caching laravel-5 key

laravel中的Cache类有get('itemKey')等方法从缓存中检索项目,并记住('itemKey',['myData1','myData2'])以保存缓存中的项目。 / p>

还有一种方法可以检查缓存中是否存在某个项目:Cache :: has('myKey');

有没有办法(使用基于文件的缓存驱动程序时)获取缓存中所有项目的列表?

例如,可能会命名为“Cache :: all()”的东西会返回:

[
    'itemKey' => [
        'myData1',
        'myData2'
   ],
   'myKey' => 'foo'
]

我能想到的唯一方法是使用Cache :: has()方法遍历所有可能的键名。即aaa,aab,aac,aad ......但当然,这不是解决方案。

我在文档或API中没有看到任何描述此类功能的内容,但我认为认为必须存在这种功能并不合理。

5 个答案:

答案 0 :(得分:9)

^以上不适用于LV 5.2

试试这个解决方案:

    $storage = \Cache::getStore(); // will return instance of FileStore
    $filesystem = $storage->getFilesystem(); // will return instance of Filesystem
    $dir = (\Cache::getDirectory());
    $keys = [];
    foreach ($filesystem->allFiles($dir) as $file1) {

        if (is_dir($file1->getPath())) {

            foreach ($filesystem->allFiles($file1->getPath()) as $file2) {
                $keys = array_merge($keys, [$file2->getRealpath() => unserialize(substr(\File::get($file2->getRealpath()), 10))]);
            }
        }
        else {

        }
    }

答案 1 :(得分:7)

使用缓存外观无法做到这一点。它的界面代表所有底层存储提供的功能,而某些商店不允许列出所有密钥。

如果您使用的是 FileCache ,则可以尝试通过直接与底层存储进行交互来实现这一目标。它不提供您需要的方法,因此您需要遍历缓存目录。由于可能需要进行大量磁盘I / O,因此效率不高。

要访问存储空间,您需要执行

$storage = Cache::getStore(); // will return instance of FileStore
$filesystem = $storage->getFilesystem(); // will return instance of Filesystem

$keys = [];
foreach ($filesystem->allFiles('') as $file1) {
  foreach ($filesystem->allFiles($file1) as $file2) {
    $keys = array_merge($keys, $filesystem->allFiles($file1 . '/' . $file2));
  }
}

答案 2 :(得分:0)

对于Memcached,您可以执行以下操作:

cache()->getMemcached()->getAllKeys()
  1. 获取Illuminate\Cache\CacheManager
  2. 获取Memcachedhttp://php.net/manual/de/class.memcached.php
  3. getAllKeys()http://php.net/manual/de/memcached.getallkeys.php

这为您提供了一系列可以通过的键。

答案 3 :(得分:0)

\config\database.php中为缓存创建Redis存储

   // store cache in their own redis store ...
    'cache-connection' => [
        'host'               => ...,
        'password'           => ...,
        'port'               => env('REDIS_PORT', 6379),
        'database'           => 2,
        'read_write_timeout' => 60,
        'timeout'            => 6.0,
    ],

\config\cache.php中使用此Redis数据库

'stores' => [
   ...
   'redis' => [
        'driver'     => 'redis',
        'connection' => 'cache-connection',
    ],
],

现在您可以使用Redis类检查缓存中的内容

$a = Redis::connection('cache-connection')->keys('*');
\Log::debug($a);

答案 4 :(得分:0)

我知道这是一个老问题,但前几天我遇到了这个问题,并且在任何地方都找不到文件存储系统的解决方案。

我的用例是我希望能够根据句号分隔组的命名约定进行删除。例如,cache()->forget('foo') 不会删除键 foo.bar

它的工作方式是保留一个 json 编码数组,其中包含您添加到文件存储中的所有键,然后当您想删除它时循环遍历,如果匹配,则将其删除。这也可能对您有用,但如果不是,您的用例可以使用现在也可以使用的 cache()->getKeys() 方法。

要遵循的步骤:

在您的 AppServiceProvider.php register 方法中添加以下内容:

use Illuminate\Support\Facades\Cache;
use App\Extensions\FileStore;
...
$this->app->booting(function () {
    Cache::extend('file', function ($app) {
        return Cache::repository(new FileStore($app['files'], config('cache.stores.file.path'), null));
    });
});

然后在 app 中创建一个名为 Extensions 的新目录。在名为 Extensions 的新 FileStore.php 目录中添加一个包含以下内容的新文件:

<?php

namespace App\Extensions;

class FileStore extends \Illuminate\Cache\FileStore
{
    /**
     * Get path for our keys store
     * @return string
     */
    private function keysPath()
    {
        return storage_path(implode(DIRECTORY_SEPARATOR, ['framework','cache','keys.json']));
    }

    /**
     * Get all keys from our store
     * @return array
     */
    public function getKeys()
    {
        if (!file_exists($this->keysPath())) {
            return [];
        }

        return json_decode(file_get_contents($this->keysPath()), true) ?? [];
    }

    /**
     * Save all keys to file
     * @param  array $keys
     * @return bool
     */
    private function saveKeys($keys)
    {
        return file_put_contents($this->keysPath(), json_encode($keys)) !== false;
    }

    /**
     * Store a key in our store
     * @param string $key [description]
     */
    private function addKey($key)
    {
        $keys = $this->getKeys();

        // Don't add duplicate keys into our store
        if (!in_array($key, $keys)) {
            $keys[] = $key;
        }

        $this->saveKeys($keys);
    }

    // -------------------------------------------------------------------------
    // LARAVEL METHODS
    // -------------------------------------------------------------------------

    /**
     * Store an item in the cache for a given number of seconds.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @param  int  $seconds
     * @return bool
     */
    public function put($key, $value, $seconds)
    {
        $this->addKey($key);
        return parent::put($key, $value, $seconds);
    }

    /**
     * Remove an item from the cache.
     *
     * @param  string  $key
     * @return bool
     */
    public function forget($forgetKey, $seperator = '.')
    {
        // Get all stored keys
        $storedKeys = $this->getKeys();

        // This value will be returned as true if we match at least 1 key
        $keyFound = false;

        foreach ($storedKeys as $i => $storedKey) {
            // Only proceed if stored key starts with OR matches forget key
            if (!str_starts_with($storedKey, $forgetKey.$seperator) && $storedKey != $forgetKey) {
                continue;
            }

            // Set to return true after all processing
            $keyFound = true;

            // Remove key from our records
            unset($storedKeys[$i]);
            
            // Remove key from the framework
            parent::forget($storedKey);
        }

        // Update our key list
        $this->saveKeys($storedKeys);

        // Return true if at least 1 key was found
        return $keyFound;
    }
    
    /**
     * Remove all items from the cache.
     *
     * @return bool
     */
    public function flush()
    {
        $this->saveKeys([]);
        return parent::flush();
    }
}