5

My module uses hook_node_view() to add some contents to the node view.

function example_node_view() {
  if ($view_mode == 'full' && $node->bundle() == 'example') 

  // Insert file listing content part
    $contents = Class::getContents();
    $build['example'] = $contents;
}

Drupal 8 caches the node view by default and only calls hook_node_view() once after each cache rebuild. For this module to function, hook_node_view() should run every time the node is requested. So, I am looking for ways to invalidate node:nid cache tag.

NB: - I am not looking for ways to disable the caching for a development.

public function getContents(){
  return [
    "#type" = 'table',
    "#header' = 'header',
     .....
  ];

Solved by adding the CacheDependency to hook_node_view() as indicated by @4k4

$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($build, $node->id());
10
  • Have you tried going to Configuration > Development > Performance? (I'm getting this off the top of my head for D7, it might be a little different for D8) Commented Dec 11, 2016 at 8:03
  • Where is $content coming from? Is this from the database or external? How often does this change?
    – 4uk4
    Commented Dec 11, 2016 at 9:14
  • @chris-happy, thanks, but I am not trying to clear chache, I want to invalidate the cache-tag for the node requested.
    – JoopSJ
    Commented Dec 11, 2016 at 9:50
  • @4k4 $contents is created trough some Classes and has it's own caching.
    – JoopSJ
    Commented Dec 11, 2016 at 9:53
  • @Bundio, I'm not sure, what exactly is in $contents. I've based my answer on files, but this works for all database content.
    – 4uk4
    Commented Dec 11, 2016 at 11:05

1 Answer 1

9

For new content added to $build you have also add the cache metadata.

Example if you add data from a file entity do this:

$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($build, $file);

This adds the cache tag for the file and whenever this file is changed, the cache item of the node which contains information from the file gets invalidated.

If the added $content is already a render array with cache metadata drupal will merge this. You can check, which cache tags are missing in $content and add them in the class that generates this data.

Reference: https://www.drupal.org/docs/8/api/render-api/cacheability-of-render-arrays

If what the comment in the code suggests you have a list of files, you can add the tag 'file_list'. All entities invalidate the tag [entity-type]_list when creating, changing or deleting an entity.

Edit:

If you use the standard tools, that is building single entity displays with the view() method and list of entities with Views, then you don't need to take care of cache dependencies, because the render arrays these tools produce contain all necessary cache metadata.

2
  • I have included a sample function how $contents is created. Indeed it returns a render array. If I understand well I can add a tag to this array and associate it with the node view owning this custom content. But I don't understands how that works because getContents() will only run when hook_view() runs and that will only run when the node cache is invalidated.
    – JoopSJ
    Commented Dec 11, 2016 at 11:25
  • 1
    You tag the node with all entities it contains. For example if you have a node with a author and a file field, then you have three tags, from the node itself, the author and the file(s). If any of them are changed, then the cached node is invalidated and will be rebuilt in the next request for the node. As long as all of the content of the node remains unchanged, there is no need to run the code again, because this would produce the same result as the cached version.
    – 4uk4
    Commented Dec 11, 2016 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.