如何通过 Laravel 5 中的键获取所有缓存项的列表?
How to get list of all cached items by key in Laravel 5?
laravel中的Cacheclass有get('itemKey')等方法从缓存中取回item,记得('itemKey',['myData1', 'myData2']) 将项目保存在缓存中。
还有一种检查缓存中是否存在项目的方法:Cache::has('myKey');
有什么方法(当使用基于文件的缓存驱动程序时)获取缓存中所有项目的列表?
例如,可以命名为 "Cache::all()" 的东西 return:
[
'itemKey' => [
'myData1',
'myData2'
],
'myKey' => 'foo'
]
我能想到的唯一方法是使用 Cache::has() 方法遍历所有可能的键名。即 aaa、aab、aac、aad...当然,这不是解决方案。
我在文档或 API 中看不到任何描述此类功能的内容,但我认为相信它必须存在是不合理的。
无法使用 Cache 门面来做到这一点。它的界面代表了所有底层存储提供的功能,一些存储不允许列出所有键。
如果您正在使用 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));
}
}
旧的答案在 Laravel 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 {
}
}
在'yourKeyGoesHere'中,您可以插入一个与*相同的字符串,或者直接插入完全相同的键。
$redis = Cache::getRedis();
$a_keys = $redis->keys("*yourKeyGoesHere*");
foreach ($a_keys as $key){
//Your Action ...
//For example forget key
$redis->del($key);
}
对于 Memcached,您可以这样做:
cache()->getMemcached()->getAllKeys()
- 得到
Illuminate\Cache\CacheManager
- 获取
Memcached
:http://php.net/manual/de/class.memcached.php
getAllKeys()
: http://php.net/manual/de/memcached.getallkeys.php
这为您提供了一组可以通过的键。
在\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 class 检查缓存中的内容
$a = Redis::connection('cache-connection')->keys('*');
\Log::debug($a);
我知道这是一个老问题,但前几天我 运行 研究过这个问题,但在任何地方都找不到文件存储系统的解决方案。
我的用例是我希望能够根据句号分隔组的命名约定进行删除。例如 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
的新目录。在名为 FileStore.php
的新 Extensions
目录中添加一个新文件,内容如下:
<?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();
}
}
步骤 1
// Add Namespace
use Illuminate\Support\Facades\Redis;
步骤 2
// Get All Available Keys
$cacheKeys = Redis::connection('cache')->keys('*');
步骤 3
// Laravel DDD
ddd($cacheKeys);
或
// PHP Variable Dump
var_dump($cacheKeys);
laravel中的Cacheclass有get('itemKey')等方法从缓存中取回item,记得('itemKey',['myData1', 'myData2']) 将项目保存在缓存中。
还有一种检查缓存中是否存在项目的方法:Cache::has('myKey');
有什么方法(当使用基于文件的缓存驱动程序时)获取缓存中所有项目的列表?
例如,可以命名为 "Cache::all()" 的东西 return:
[
'itemKey' => [
'myData1',
'myData2'
],
'myKey' => 'foo'
]
我能想到的唯一方法是使用 Cache::has() 方法遍历所有可能的键名。即 aaa、aab、aac、aad...当然,这不是解决方案。
我在文档或 API 中看不到任何描述此类功能的内容,但我认为相信它必须存在是不合理的。
无法使用 Cache 门面来做到这一点。它的界面代表了所有底层存储提供的功能,一些存储不允许列出所有键。
如果您正在使用 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));
}
}
旧的答案在 Laravel 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 {
}
}
在'yourKeyGoesHere'中,您可以插入一个与*相同的字符串,或者直接插入完全相同的键。
$redis = Cache::getRedis();
$a_keys = $redis->keys("*yourKeyGoesHere*");
foreach ($a_keys as $key){
//Your Action ...
//For example forget key
$redis->del($key);
}
对于 Memcached,您可以这样做:
cache()->getMemcached()->getAllKeys()
- 得到
Illuminate\Cache\CacheManager
- 获取
Memcached
:http://php.net/manual/de/class.memcached.php getAllKeys()
: http://php.net/manual/de/memcached.getallkeys.php
这为您提供了一组可以通过的键。
在\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 class 检查缓存中的内容
$a = Redis::connection('cache-connection')->keys('*');
\Log::debug($a);
我知道这是一个老问题,但前几天我 运行 研究过这个问题,但在任何地方都找不到文件存储系统的解决方案。
我的用例是我希望能够根据句号分隔组的命名约定进行删除。例如 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
的新目录。在名为 FileStore.php
的新 Extensions
目录中添加一个新文件,内容如下:
<?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();
}
}
步骤 1
// Add Namespace
use Illuminate\Support\Facades\Redis;
步骤 2
// Get All Available Keys
$cacheKeys = Redis::connection('cache')->keys('*');
步骤 3
// Laravel DDD
ddd($cacheKeys);
或
// PHP Variable Dump
var_dump($cacheKeys);