Cache API

Information about the Drupal Cache API

Basics

Note: If not specified, all of the methods mentioned here belong to \Drupal\Core\Cache\CacheBackendInterface.

The Cache API is used to store data that takes a long time to compute. Caching can be permanent, temporary, or valid for a certain timespan, and the cache can contain any type of data.

To use the Cache API:

  • Request a cache object through \Drupal::cache() or by injecting a cache service.
  • Define a Cache ID (cid) value for your data. A cid is a string, which must contain enough information to uniquely identify the data. For example, if your data contains translated strings, then your cid value must include the current interface language.
  • Call the get() method to attempt a cache read, to see if the cache already contains your data.
  • If your data is not already in the cache, compute it and add it to the cache using the set() method. The third argument of set() can be used to control the lifetime of your cache item.

Example:

$cid = 'mymodule_example:' . \Drupal::languageManager()->getCurrentLanguage()->id();

$data = NULL;
if ($cache = \Drupal::cache()->get($cid)) {
  $data = $cache->data;
}
else {
  $data = my_module_complicated_calculation();
  \Drupal::cache()->set($cid, $data);
}

Note the use of $data and $cache->data in the above example. Calls to \Drupal::cache()->get() return a record that contains the information stored by \Drupal::cache()->set() in the data property as well as additional meta information about the cached data. In order to make use of the cached data you can access it via $cache->data.

Cache bins

Cache storage is separated into "bins", each containing various cache items. Each bin can be configured separately; see Configuration.

When you request a cache object, you can specify the bin name in your call to \Drupal::cache(). Alternatively, you can request a bin by getting service "cache.nameofbin" from the container. The default bin is called "default", with service name "cache.default", it is used to store common and frequently used caches.

Other common cache bins are the following:

  • bootstrap: Small caches needed for the bootstrap on every request.
  • render: Contains cached HTML strings like cached pages and blocks, can grow to large size.
  • data: Contains data that can vary by path or similar context.
  • discovery: Contains cached discovery data for things such as plugins, views_data, or YAML discovered data such as library info.

A module can define a cache bin by defining a service in its modulename.services.yml file as follows (substituting the desired name for "nameofbin"):

cache.nameofbin:
  class: Drupal\Core\Cache\CacheBackendInterface
  tags:
    - { name: cache.bin }
  factory_method: get
  factory_service: cache_factory
  arguments: [nameofbin]

Deletion

There are two ways to remove an item from the cache:

  • Deletion (using delete(), deleteMultiple() or deleteAll()) permanently removes the item from the cache.
  • Invalidation (using invalidate(), invalidateMultiple() or invalidateAll()) is a "soft" delete that only marks items as "invalid", meaning "not fresh" or "not fresh enough". Invalid items are not usually returned from the cache, so in most ways they behave as if they have been deleted. However, it is possible to retrieve invalid items, if they have not yet been permanently removed by the garbage collector, by passing TRUE as the second argument for get($cid, $allow_invalid).

Use deletion if a cache item is no longer useful; for instance, if the item contains references to data that has been deleted. Use invalidation if the cached item may still be useful to some callers until it has been updated with fresh data. The fact that it was fresh a short while ago may often be sufficient.

Invalidation is particularly useful to protect against stampedes. Rather than having multiple concurrent requests updating the same cache item when it expires or is deleted, there can be one request updating the cache, while the other requests can proceed using the stale value. As soon as the cache item has been updated, all future requests will use the updated value.

Cache Tags

The fourth argument of the set() method can be used to specify cache tags, which are used to identify what type of data is included in each cache item. Each cache item can have multiple cache tags, and each cache tag has a string key and a value. The value can be:

  • TRUE, to indicate that this type of data is present in the cache item.
  • An array of values. For example, the "node" tag indicates that particular node's data is present in the cache item, so its value is an array of node IDs.

Data that has been tagged can be deleted or invalidated as a group: no matter the Cache ID (cid) of the cache item, no matter in which cache bin a cache item lives; as long as it is tagged with a certain cache tag, it will be deleted or invalidated.

Because of that, cache tags are a solution to the cache invalidation problem:

  • For caching to be effective, each cache item must only be invalidated when absolutely necessary. (i.e. maximizing the cache hit ratio.)
  • For caching to be correct, each cache item that depends on a certain thing must be invalidated whenever that certain thing is modified.

A typical scenario: a user has modified a node that appears in two views, three blocks and on twelve pages. Without cache tags, we couldn't possibly know which cache items to invalidate, so we'd have to invalidate everything: we had to sacrifice effectiveness to achieve correctness. With cache tags, we can have both.

Example:

// A cache item with nodes, users, and some custom module data.
$tags = array(
  'my_custom_tag' => TRUE,
  'node' => array(1, 3),
  'user' => array(7),
);
\Drupal::cache()->set($cid, $data, CacheBackendInterface::CACHE_PERMANENT, $tags);

// Delete or invalidate all cache items with certain tags.
\Drupal\Core\Cache\Cache::deleteTags(array('node' => array(1));
\Drupal\Core\Cache\Cache::invalidateTags(array('user' => array(1)));

Drupal is a content management system, so naturally you want changes to your content to be reflected everywhere, immediately. That's why we made sure that every entity type in Drupal 8 automatically has support for cache tags: when you save an entity, you can be sure that the cache items that have the corresponding cache tags will be invalidated. This also is the case when you define your own entity types: you'll get the exact same cache tag invalidation as any of the built-in entity types, with the ability to override any of the default behavior if needed. See \Drupal\Core\Entity\EntityInterface::getCacheTag(), \Drupal\Core\Entity\EntityInterface::getListCacheTags(), \Drupal\Core\Entity\Entity::invalidateTagsOnSave() and \Drupal\Core\Entity\Entity::invalidateTagsOnDelete().

@todo Update cache tag deletion in https://drupal.org/node/918538

Configuration

By default cached data is stored in the database. This can be configured though so that all cached data, or that of an individual cache bin, uses a different cache backend, such as APC or Memcache, for storage.

In a settings.php file, you can override the service used for a particular cache bin. For example, if your service implementation of \Drupal\Core\Cache\CacheBackendInterface was called cache.custom, the following line would make Drupal use it for the 'cache_render' bin:

 $settings['cache']['bins']['render'] = 'cache.custom';

Additionally, you can register your cache implementation to be used by default for all cache bins with:

 $settings['cache']['default'] = 'cache.custom';

See also

https://drupal.org/node/1884796

Functions

Namesort descending Location Description
Drupal::cache drupal/core/lib/Drupal.php Returns the requested cache bin.

Classes

Namesort descending Location Description
Cache drupal/core/lib/Drupal/Core/Cache/Cache.php Helper methods for cache.
CacheCollector drupal/core/lib/Drupal/Core/Cache/CacheCollector.php Default implementation for CacheCollectorInterface.
ChainedFastBackend drupal/core/lib/Drupal/Core/Cache/ChainedFastBackend.php Defines a backend with a fast and a consistent backend chain.
DatabaseBackend drupal/core/lib/Drupal/Core/Cache/DatabaseBackend.php Defines a default cache implementation.
MemoryBackend drupal/core/lib/Drupal/Core/Cache/MemoryBackend.php Defines a memory cache implementation.
NullBackend drupal/core/lib/Drupal/Core/Cache/NullBackend.php Defines a stub cache implementation.
PhpBackend drupal/core/lib/Drupal/Core/Cache/PhpBackend.php Defines a PHP cache implementation.

Interfaces

Namesort descending Location Description
CacheableInterface drupal/core/lib/Drupal/Core/Cache/CacheableInterface.php Defines an interface for objects which are potentially cacheable.
CacheBackendInterface drupal/core/lib/Drupal/Core/Cache/CacheBackendInterface.php Defines an interface for cache implementations.
CacheCollectorInterface drupal/core/lib/Drupal/Core/Cache/CacheCollectorInterface.php Provides a caching wrapper to be used in place of large structures.

File

drupal/core/modules/system/core.api.php, line 684
Documentation landing page and topics, plus core library hooks.