1

I am implementing hook_entity_view() in my module. In the hook I am adding a link to the node by rendering a array. The links need to be added only when a certain configuration condition becomes TRUE. The code which I have written is something like this:

function module_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode) {
  $condition = \Drupal::service('config.factory')->get('module.settings')->get('variable');
  if ($condition is TRUE) {
    return render array which adds links;
  }
}

The problem with above code is that even when I have updated my configuration setting and then refresh node page there is no effect of change in configuration in rendering of node's content. But when I have cleared cache the effect immediately shows.When should I do so that I need not to clear cache? Thanks.

2
  • This is normal, in Drupal 7 is identical. Drupal save the page in cache on the first request. Test it on other browser or other node on the same browser, you will see working.
    – rpayanm
    Jun 19, 2015 at 21:25
  • No, it's not identical in Drupal 7. Drupal 8 has many more caches, rendered entities are cached for all users (possibly in different variations). However, using cache tags as explained in my answer will also give you page cache invalidation, automatically, for free.
    – Berdir
    Jun 19, 2015 at 22:16

1 Answer 1

1

The answer is exactly the same as an existing question you asked, even though the question was quite different.

The answer is: cache tags or more generic, cache metadata.

Quoting myself from https://drupal.stackexchange.com/a/160982/31:

Blocks are cached by default.

You don't need to manually clear those caches when you change your configuration, but you need to flag/tag your blocks output to tell Drupal that your block output depends on your configuration.

Read the Cacheability documentation. What you need is something like this:

$output['#cache']['tags'] = $config->getCacheTags();

Just replace block with entity in the description and you have your answer. Note that when doing something conditional, you must always add the cache tags/context, meaning, outside of the if condition, not inside.

I just realized my code sample there is problematic when you alter existing render arrays, because you risk overwriting existing cache tags. So you should use what the referenced documentation does, that ensures that existing cache tags are kept:

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

That basically reads "$build depends on $config".

Memorize that link and the steps there. Always check them you add or change render arrays:

The thought process

Please try to adopt the following thought process.

Whenever you are generating a render array, use the following 5 steps:

  1. I'm rendering something. That means I must think of cacheability.
  2. Is this something that's expensive to render, and therefore is worth caching? If the answer is "yes", then what identifies this particular representation of the thing I'm rendering? Those are the cache keys.
  3. Does the representation of the thing I'm rendering vary per combination of permissions, per URL, per interface language, per … something? Those are the cache contexts. Note: cache contexts are completely analogous to HTTP's Vary header.
  4. What causes the representation of the thing I'm rendering become outdated? I.e. which things does it depend upon, so that when those things change, so should my representation? Those are the cache tags.
  5. When does the representation of the thing I'm rendering become outdated? I.e. is the data valid for a limited period of time only? That is the max-age (maximum age). It defaults to "permanently (forever) cacheable" (Cache::PERMANENT). When the representation is only valid for a limited time, set a max-age, expressed in seconds. Zero means that it's not cacheable at all.

Cache contexts, tags and max-age must always be set, because they affect the cacheability of the entire response. Therefore they "bubble": parents automatically receive them.

Cache keys must only be set if the render array should be cached.

2
  • thanks so should I do something like this: $build['#cache']['tags'] = $entity->getCacheTags(); in the above hook ? Jun 20, 2015 at 5:30
  • No, not the entity. The entity cache tags are already there, that's not what you depend on. You depend on your configuration, so that's what you need. Exactly what's in the quoted text. However, I realized that the code example there is problematic, because you risk to overwrite existing cache tags. I'll update it based on what the documentation is using.
    – Berdir
    Jun 20, 2015 at 7:49

Your Answer

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

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