Skip to main content
Drupal is a registered trademark of Dries Buytaert
Release: OpenID Connect / OAuth client 3.0.0-alpha9 New alpha version released for module openid_connect (3.0.0-alpha9). Usage Milestone: Google Analytics Module google_analytics crossed 1,000 active installs. Release: Timelinr 1.0.1 Minor update available for module timelinr (1.0.1). Release: GraphQL Compose Codegen 1.1.2 Minor update available for module graphql_compose_codegen (1.1.2). Release: Mapy.com 1.1.3 Minor update available for module mapycom (1.1.3). Release: Ckeditor5 entity browser 3.0.3 Minor update available for module ckeditor5_entity_browser (3.0.3). Release: Ckeditor5 entity browser 3.0.1 Minor update available for module ckeditor5_entity_browser (3.0.1). Release: Ckeditor5 entity browser 3.0.2 Minor update available for module ckeditor5_entity_browser (3.0.2). Release: Teamleader Integration 4.0.2 Minor update available for module teamleader (4.0.2). Module Revived: Entityqueue Buttons 1.1.2 Module entityqueue_buttons updated after 8 months of inactivity (1.1.2).

Cache Register

10 sites Security covered Drupal 8–11
View on drupal.org

Cache Register simplifies caching custom data by organizing cache entries into named "Drawers," "Slots," and "Registers." This system reduces boilerplate code and helps developers avoid manually managing cache IDs. It provides an intuitive API for setting, retrieving, and invalidating cached data.

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

Depends on

Dependencies of the latest stable release

No dependencies recorded for this project.

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
5
Tracked since
Jan 2026
Latest release
7 months ago
Releases (12 mo)
5 ▲ from 0
Maintenance
Slowing

Release Timeline

Releases

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