$npx -y skills add edutrul/drupal-ai --skill drupal-cachingDrupal Cache API — cache tags, contexts, max-age, cache bins, invalidation, and adding cache metadata to render arrays.
| 1 | # Drupal Caching |
| 2 | |
| 3 | **Always add cache metadata. Missing cache metadata causes stale content.** |
| 4 | |
| 5 | ## Cache Metadata in Render Arrays |
| 6 | |
| 7 | ```php |
| 8 | $build['content'] = [ |
| 9 | '#markup' => $output, |
| 10 | '#cache' => [ |
| 11 | 'tags' => ['node:' . $node->id(), 'node_list'], |
| 12 | 'contexts' => ['user.permissions', 'url.query_args'], |
| 13 | 'max-age' => Cache::PERMANENT, |
| 14 | ], |
| 15 | ]; |
| 16 | ``` |
| 17 | |
| 18 | ## Cache Tags |
| 19 | |
| 20 | | Tag | Invalidated when | |
| 21 | |---|---| |
| 22 | | `node:{nid}` | Node {nid} is saved/deleted | |
| 23 | | `node_list` | Any node is created or deleted | |
| 24 | | `user:{uid}` | User {uid} is saved | |
| 25 | | `taxonomy_term:{tid}` | Term {tid} is saved | |
| 26 | | `config:{name}` | Config object {name} is saved | |
| 27 | |
| 28 | ## Cache Contexts |
| 29 | |
| 30 | | Context | Varies by | |
| 31 | |---|---| |
| 32 | | `user.permissions` | User's permissions (prefer over `user`) | |
| 33 | | `user.roles` | User's roles | |
| 34 | | `url.path` | URL path | |
| 35 | | `url.query_args` | Query parameters | |
| 36 | | `languages` | Current language | |
| 37 | |
| 38 | ## Reading/Writing Cache |
| 39 | |
| 40 | ```php |
| 41 | $cached = $this->cacheBackend->get('my_module:my_key'); |
| 42 | if ($cached !== FALSE) { |
| 43 | return $cached->data; |
| 44 | } |
| 45 | |
| 46 | $this->cacheBackend->set('my_module:my_key', $data, Cache::PERMANENT, ['node_list']); |
| 47 | $this->cacheBackend->set('my_module:my_key', $data, \Drupal::time()->getRequestTime() + 3600, ['node_list']); |
| 48 | $this->cacheBackend->delete('my_module:my_key'); |
| 49 | |
| 50 | Cache::invalidateTags(['node:123', 'node_list']); |
| 51 | ``` |
| 52 | |
| 53 | ## Inject Cache Service |
| 54 | |
| 55 | ```php |
| 56 | use Drupal\Core\Cache\CacheBackendInterface; |
| 57 | |
| 58 | public function __construct( |
| 59 | private readonly CacheBackendInterface $cacheBackend, |
| 60 | ) {} |
| 61 | ``` |
| 62 | |
| 63 | ```yaml |
| 64 | # services.yml |
| 65 | my_module.my_service: |
| 66 | arguments: ['@cache.default'] |
| 67 | ``` |
| 68 | |
| 69 | ## CacheableDependencyInterface |
| 70 | |
| 71 | ```php |
| 72 | $build['#cache']['tags'] = Cache::mergeTags( |
| 73 | $build['#cache']['tags'] ?? [], |
| 74 | $node->getCacheTags() |
| 75 | ); |
| 76 | ``` |