16

I'm working on a module in Drupal 8 which retrieves time sensitive data from an external REST api. The data is processed and forwarded to a Block. The final data is sent to a Twig template like so:

...

public function build() {
  $build = [];

  $build['ticker_block'] = [
    '#theme' => 'module_theme',
    '#data' => $myService->data(),
  ];

  return $build;
}

This doesn't work on the production environment where cache is enabled and the rendered data shows up as stale. How do I disable cache for my module only, and do I have to do it for both the Twig template and Block plugin?

5 Answers 5

28

You can control the cache in the render array with the #cache element.

To disable the cache add:

$build['#cache']['max-age'] = 0;

In this case the block will not be cached for logged in users or anonymous users with a session.

If you want to disable the cache for anonymous users without a session:

Disable it either by uninstalling the page_cache module completely or by triggering the kill switch, see How can I prevent a particular page being cached? for example.

The caching of the twig code is not connected to this, the twig code is only cached once, the first time it is used after you cleared the cache.

(edit acc. to comments of Berdir)

6
  • I suppose a cache context won't help in this specific case, but maybe you want to use an actual max-age instead of 0 which disabled caching completely, like 60. Not sure how time sensitive your data is, but usually, things can be cached for a minute or a few. Also, note that max-age does not affect the anonymous page cache. If you need this for anonymous users, you need to disable that completely or fetch the data using javascript.
    – Berdir
    Dec 29, 2015 at 16:51
  • @Berdir: I use the max-age=0 for anonymous users, but with sessions. This is working now in dev. Do you think this is OK for production? What do you mean with disable completely?
    – 4uk4
    Dec 29, 2015 at 17:36
  • It's fine if you have sessions, then it works. Disable it either by uninstalling the page_cache module completely or by triggering the kill switch, see drupal.stackexchange.com/questions/151254/… for example.
    – Berdir
    Dec 29, 2015 at 17:38
  • Thank you for the great info, i've added this in the answer.
    – 4uk4
    Dec 29, 2015 at 17:52
  • 1
    $build['#cache']['max-age'] = 0; did the trick !!! Beers all round! :)
    – Sorin
    Jan 12, 2016 at 16:18
9

To stop caching a specific block use the following function:

/**
 * Implements hook_preprocess_HOOK() for block.html.twig.
 */
function template-name_preprocess_block(&$vars) {
  if($vars['derivative_plugin_id'] == 'add-block-id-name') {
    //-- This stops the block being cache in drupal 8
    $vars['#cache']['max-age'] = 0;
  }
}
1
  • Excellent answer.
    – Pupil
    Mar 18, 2019 at 5:15
6

Disable cache for a specific page/content type/controller

Disable cache for a custom page from route declaration.

If you want to disable cache for a custom controller (Custom module), You have no_cache option (YOUR_MODULE.routing.yml). Example : File : mymodule.routing.yml

mymodule.myroute:
  path: '/mymodule/mypage'
  defaults:
    _controller: '\Drupal\mymodule\Controller\Pages::mypage'
    _title: 'No cache page'
  requirements:
    _access: 'TRUE'
  options:
    no_cache: 'TRUE'

Added 'no_cache' route option to mark a route's responses as uncacheable

1

To prevent caching of a particular block:

add the below code in theme_name.theme file

function theme_name_preprocess_block(&$variables) {
  if ($variables['plugin_id'] == 'block_id') {
    $variables['#cache']['max-age'] = 0;
  }
}
1

To disable the cache for a block type, preprocess the block of that type and set max_age to 0.

   /**
     * Implements hook_preprocess_HOOK() for Block document templates.
     */
    function THEMENAME_preprocess_block(array &$variables) {

      //disbale cache from spotlight
      $content = $variables['elements']['content'];
      //dump($content); //check the contents
      if (isset($content['#block_content']) && $content['#block_content'] instanceof BlockContentInterface) {

        if ($content['#block_content']->bundle() == 'BLOCK_TYPE') {
          $variables['#cache']['max-age'] = 0;
        }

      }


    }

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.