cache_register
Tired of looking up tutorials or parsing old code every time you need to cache some arbitrary data? Not sure how to name your cache entries? Cache Register to the rescue! Cache Register aims to simplify the developer experience of caching custom data.
Cache Register introduces the concept of Drawers, Slots, and Registers to help keep your cache entries organized and manageable. Let's say you hit an API for a batch of users and want to cache that information. Here's how you'd do it.
// ==================================
// Cache your data
// ==================================
$manager = \Drupal::service('cache_register.manager');
$user = \Drupal::entityTypeManager->getStorage('user')->load(1337);
$slot = $manager->openSlot('my_module', 'some_api', $user->id());
if (!$slot->isCached() {
$api_data = some_api_request($user->id());
$slot->setCache($api_data);
$slot->addCacheTags($user->getCacheTags());
// or optionally provide cache expiry and cache tags as normal
$slot->setCache($data, strtotime('+7 days'), $user->getCacheTags());
}
// ==================================
// Retrieve your data from anywhere
// ==================================
$slot = $manager->openSlot('my_module', 'some_api', $uid);
$data = $user_slot->getCacheData();
// ==================================
// Invalidate/delete the cache
// ==================================
$slot->invalidateCache();
$slot->deleteCache();
// or to invalidate all cache entries associated with a drawer
$drawer = $manager->openDrawer('my_module', 'some_api')->invalidate();
How it works
It's important to note that drawers and slots do not actually "exist" in the cache -- they just provide wrappers for interacting with a specific cache entry without so much boilerplate. It helps to stop needing to add so much boilerplate to classes like this to define your cache interactions, and to avoid passing around/keeping track of $cid variables.
// This
$slot = $manager->openSlot('my_module', 'some_api', $uid);
if(!$slot->isCached()) {
$slot->setCache($some_data, strtotime('+1day'), $user->getCacheTags());
$slot->addCacheTags($node->getCacheTags());
}
// is like doing
$cid = "my_module.some_api:$uid";
if(!$this->cache->get($cid)) {
$this->cache->set($cid, $some_data, strtotime('+1day'), $user->getCacheTags());
$cache_item = $this->cache->get("my_module.some_api:$uid");
$existing_tags = $cache_item->tags;
$all_tags = Cache::mergeTags($existing_tags, $node->getCacheTags());
$this->cache->set($cid, $cache_item->data, $cache_item->expiry, $all_tags);
}
Cache Bins
Cache Register does not replace cache bins. On the contrary, it can be effectively used alongside them. PCB provides a so-called permanent cache bin to allow data to persist regular cache clears. Cache Register can interact with this or any other cache bins by injecting them into a custom service like:
// In my_module.services.yaml
cache.my_module_pcb:
class: Drupal\Core\Cache\CacheBackendInterface
tags:
- { name: cache.bin, default_backend: cache.backend.permanent_database }
factory: cache_factory:get
arguments: [ my_module_pcb ]
my_module.cache_manager:
class: Drupal\cache_register\Manager
arguments: [ '@cache.my_module_pcb' ]
my_module.some_service:
class: Drupal\my_module\Service\SomeService
arguments:
- '@my_module.cache_manager'
// Then in my_module.some_service, invoke as normal
$this->cacheManager->openSlot(...);
Shameless Self Promotion
A list of modules that I maintain:
- Cache Register: A module aimed at improving developer quality of life surrounding caching.
- Enum Generator: A developer utility that generates enums and class constants from a site's entities.
- Views Hooks Extras: Extends Views' native hooks to more specifically target particular views and their displays
- Media Entity Remote Image: Provides a simple media type + field for remote image urls