1. Now we store the tagged cache data, which is tagged with 1 tag: theme_editor_qVnbtdW6HjsG5clEw6j6ygedgjrP4A9EDIsY
return Cache::tags([
ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId]
)
->put(ThemePreviewInterface::THEME_EDITOR_SESSION_PREFIX . $sessionId, json_encode($data), ThemePreviewInterface::TTL);
2. After running the program, a total of 3 keys are generated, as shown in Figure 1.

object_local_database_object_local_cache:tag:theme_editor_qVnbtdW6HjsG5clEw6j6ygedgjrP4A9EDIsY:key
object_local_database_object_local_cache:63316a53e72ae936365540:standard_ref
object_local_database_object_local_cache:8900c8427a4e5d7ac70fed24623811c3b5330ddf:theme_editor_session:qVnbtdW6HjsG5clEw6j6ygedgjrP4A9EDIsY
3. The expiration time is set to 120 seconds. After 2 minutes, upon refreshing Redis again, only the key object_local_database_object_local_cache:8900c8427a4e5d7ac70fed24623811c3b5330ddf:theme_editor_session:qVnbtdW6HjsG5clEw6j6ygedgjrP4A9EDIsY has been automatically deleted. As shown in Figure 2.

4. This means there are still 2 redundant keys left, both related to tags. I decide to set an expiration time for both redundant keys when writing to the cache. Since I am using Laravel’s Redis cache, I decide to implement this by setting the expiration time based on Redis.
Cache::tags([
ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId]
)
->put(ThemePreviewInterface::THEME_EDITOR_SESSION_PREFIX . $sessionId, json_encode($data), ThemePreviewInterface::TTL);
$names = Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->getNames();
var_dump($names);
foreach ($names as $name) {
var_dump(Cache::getPrefix() . Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->tagKey($name));
var_dump(Redis::connection('cache')->command('expire', [Cache::getPrefix() . Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->tagKey($name), ThemePreviewInterface::TTL]));
var_dump(Cache::getPrefix() . Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->tagId($name) . ':' . RedisTaggedCache::REFERENCE_KEY_STANDARD);
var_dump(Redis::connection('cache')->command('expire', [Cache::getPrefix() . Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->tagId($name) . ':' . RedisTaggedCache::REFERENCE_KEY_STANDARD, ThemePreviewInterface::TTL]));
}
// var_dump(Cache::tags(ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId)->getTags()->getNames());
// var_dump(Cache::getPrefix());
exit;
5. The printed result is as follows. As shown in Figure 3.

array(1) {
[0]=>
string(49) "theme_editor_I37HieXlW2yzmNqWTwGsMoRu3vjivgpaGJ1T"
}
string(93) "object_local_cache:tag:theme_editor_I37HieXlW2yzmNqWTwGsMoRu3vjivgpaGJ1T:key"
bool(true)
string(71) "object_local_cache:63326932d41fb365623106:standard_ref"
bool(true)
6. 3 keys are generated in Redis, as shown in Figure 4.

object_local_database_object_local_cache:tag:theme_editor_I37HieXlW2yzmNqWTwGsMoRu3vjivgpaGJ1T:key
object_local_database_object_local_cache:63326932d41fb365623106:standard_ref
object_local_database_object_local_cache:59840c6d708feb22c6540bd14dbeb0c34bf4bbc4:theme_editor_session:I37HieXlW2yzmNqWTwGsMoRu3vjivgpaGJ1T
7. Because the expiration time is set to 120 seconds, after 2 minutes pass, the data in Redis decreases from 12 entries to 9 entries. The 3 previously generated keys have been automatically deleted. As shown in Figure 5.

8. The final implementation code is as follows
$name = ThemePreviewInterface::TAG_THEME_EDITOR . '_' . $sessionId;
$tags = Cache::tags($name);
$result = $tags->put(ThemePreviewInterface::THEME_EDITOR_SESSION_PREFIX . $sessionId, json_encode($data), ThemePreviewInterface::TTL);
if ($result) {
Redis::connection('cache')->expire(Cache::getPrefix() . $tags->getTags()->tagKey($name), ThemePreviewInterface::TTL);
Redis::connection('cache')->expire(Cache::getPrefix() . $tags->getTags()->tagId($name) . ':' . RedisTaggedCache::REFERENCE_KEY_STANDARD, ThemePreviewInterface::TTL);
}
return $result;
