Drupal 10: Cache API
Pankaj Raundal
Technical Lead at Lionbridge | AWS | Azure | Python | Drupal developer
Cache is a crucial component of any website, serving users faster and efficiently managing resource utilization. There are two types of traffic that any website can receive: Authenticated users and anonymous users. For anonymous users, pages remain unchanged, allowing them to load without variation. However, pages for authenticated users are dynamic and unique per user.
Drupal cache has undergone significant advancements compared to Drupal 6 and 7. It has come a long way, enabling dynamic caching for authenticated users, region-based caching, language-based caching, and placeholders for dynamic content.
At the Drupal level, caching is managed by two core modules:
By default, Drupal stores cache in the database. This is the default cache mechanism provided by Drupal out of the box.
One question that arises is how the cache system knows when content has changed and needs to be updated with the latest changes. Drupal handles this automatically for core systems:
While Drupal manages these aspects out of the box for core systems, when writing custom code, it's essential to ensure that the content passed via your code is updated and invalidated as necessary.
Let's consider a small example to illustrate this concept.
If you're creating a custom block or a controller and passing data to a render array through it, you also need to specify when this content needs to be revalidated. How do you do that? You can achieve this by populating the "#cache" key in render arrays.
For instance, suppose you create a custom block that displays the current user's name and your site's name. Your block would return the following render array:
$render_array = [
'#markup' => t('Hi, %name welcome back to @site', [
'%name' => $current_user-getUserName();
'@site' => $config->get('name');
]),
];
The above block is only cacheable per user since it displays the user's name. Here, we need to add Cache Context (condition), so our above render array will be modified as follows:
$render_array = [
'#markup' => t('Hi, %name welcome back to @site', [
'%name' => $current_user-getUserName();
'@site' => $config->get('name');
]),
"#cache" => [
'contexts' => ['user'],
],
];
Now, consider what will happen if you change the name of your site. In the above render array, we need to add a dependency for site configuration. As soon as it changes, the cache should be invalidated, ensuring that the block displays the latest updated site name.
$renderer->addCacheableDependecy($render_array, $config);
Similarly, the same principle applies to the user name. If a user changes their name, it should also reflect the updated user name. Therefore, we need to add a dependency on the current user.
$renderer->addCacheableDependecy($render_array, $current_user);
So, to invalidate the cache using a render array, you could add a cache key. Additionally, you could further add context, tags, or a maximum age, or all three. All these mechanisms will work simultaneously.
For example, if you set a max-age of 1 hour and a cache tag as 'node:5', then in practice, Drupal will check the status of 'node:5'. If it hasn't been updated, Drupal will then check if the content has crossed the maximum age (time to live) of 1 hour. If either condition is true, it will invalidate the cache and fetch new or updated content.
领英推荐
Cache tag bubbling:
Markup should generally be passed to the theme layer via render arrays. Cacheability details are added to the render array. We set: cache tags, cache context, and cache max-age.
Examples of cache tags:
Let’s see some more examples of setting cache information:
pubic function build(){
return [
'#markup' => some_fucntion_returns_markup(),
'#cache' => [
'tags' => ['node_list'], // Invalidate this block when any node updates
'context' => ['user']. // New cache item per individual user
'max-age' => \Drupal\Core\Cache\Cache::PERMANENT,
// More Example......
// 'tags' => ['node:1', 'term:2'], // invalidate this block if node 1 or term 2 updates
// 'max-age' => 60, // Cache expires after 60 seconds
// 'max-age' => 0 // Cache for 0 seconds, i.e never cached
],
]
}
Where is the Cache Saved?
By default, cache is saved in the database, and core cache modules are enabled by default. Other options to store cache include:
Once your site is set up, there are many layers of caching. The database stores Drupal's cache and cache for database queries. Opcache or APC cache the actual PHP code.
For Varnish:
Content Delivery Network (CDN) can also cache whole pages:
In summary, serving requests from cache appears as follows:
I hope this article provides a brief overview of caching and how it operates in Drupal. Much of the content is derived from the following YouTube video, which you can also reference for further understanding:
Additionally, caching is extensively covered on Drupalize.me.