Drupal is a registered trademark of Dries Buytaert
drupal 11.3.7 Update released for Drupal core (11.3.7)! drupal 11.2.11 Update released for Drupal core (11.2.11)! drupal 10.6.7 Update released for Drupal core (10.6.7)! drupal 10.5.9 Update released for Drupal core (10.5.9)! cms 2.1.1 Update released for Drupal core (2.1.1)! drupal 11.3.6 Update released for Drupal core (11.3.6)! drupal 10.6.6 Update released for Drupal core (10.6.6)! cms 2.1.0 Update released for Drupal core (2.1.0)! bootstrap 8.x-3.40 Minor update available for theme bootstrap (8.x-3.40). menu_link_attributes 8.x-1.7 Minor update available for module menu_link_attributes (8.x-1.7). eca 3.1.1 Minor update available for module eca (3.1.1). layout_paragraphs 2.1.3 Minor update available for module layout_paragraphs (2.1.3). ai 1.3.3 Minor update available for module ai (1.3.3). ai 1.2.14 Minor update available for module ai (1.2.14). node_revision_delete 2.0.3 Minor update available for module node_revision_delete (2.0.3). moderated_content_bulk_publish 2.0.52 Minor update available for module moderated_content_bulk_publish (2.0.52). klaro 3.0.10 Minor update available for module klaro (3.0.10). klaro 3.0.9 Minor update available for module klaro (3.0.9). layout_paragraphs 2.1.2 Minor update available for module layout_paragraphs (2.1.2). geofield_map 11.1.8 Minor update available for module geofield_map (11.1.8).

cache_register

8 sites Security covered
View on drupal.org

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

Activity

Total releases
5
First release
Jan 2026
Latest release
2 months ago
Release cadence
1 day
Stability
80% stable

Release Timeline

Releases

Version Type Release date
1.1.x-dev Dev Jan 26, 2026
1.1.1 Stable Jan 26, 2026
1.1.0 Stable Jan 26, 2026
1.0.4 Stable Jan 23, 2026
1.0.3 Stable Jan 23, 2026