I know this is an old thread, but thought I'd post this anyway - a Macro that does as you'd expect:
Cache::macro('getAll', function (): array {
if (! $this instanceof TaggedCache) {
throw new BadMethodCallException('The getAll macro may only be used on a tagged cache instance (e.g. Cache::tags([...])->getAll()).');
}
$tagSet = $this->getTags();
if (! $tagSet instanceof RedisTagSet) {
throw new BadMethodCallException('The getAll macro is only supported when using the Redis cache store with tags.');
}
$names = $tagSet->getNames();
if ($names === []) {
return [];
}
$store = $this->getStore();
$prefix = $store->getPrefix();
$connection = $store->connection();
$firstName = $names[0];
$otherNames = array_slice($names, 1);
$firstTagSet = new RedisTagSet($store, [$firstName]);
$uniqueStorageKeys = [];
foreach ($firstTagSet->entries()->unique() as $storageKey) {
if ($storageKey === '' || $storageKey === null) {
continue;
}
$include = true;
foreach ($otherNames as $otherTagName) {
$zsetKey = $prefix.'tag:'.$otherTagName.':entries';
$score = $connection->zscore($zsetKey, $storageKey);
if ($score === false || $score === null) {
$include = false;
break;
}
}
if (! $include) {
continue;
}
$uniqueStorageKeys[(string) $storageKey] = true;
}
$storageKeys = array_keys($uniqueStorageKeys);
if ($storageKeys === []) {
return [];
}
$values = [];
foreach (array_chunk($storageKeys, 1000) as $chunk) {
foreach ($store->many($chunk) as $storageKey => $value) {
if ($value === null) {
continue;
}
$logicalKey = str_contains((string) $storageKey, ':')
? explode(':', (string) $storageKey, 2)[1]
: (string) $storageKey;
$values[$logicalKey] = $value;
}
}
return $values;
});
You can then get all the items with any combination of tags.
Cache::tags(['tag1', 'tag2', 'tag3'])->put('item1', 1);
Cache::tags(['tag1', 'tag4'])->put('item1', 2);
Cache::tags(['tag1', 'tag3'])->put('item1', 3);
Cache::tags(['tag1', 'tag2', 'tag3'])->getAll();
// item 1
Cache::tags(['tag1'])->getAll();
// item1, item 2, item 3
Cache::tags(['tag3'])->getAll();
// item 1, item 3