Block caching examples

Block caching examples

The following examples will use custom blocks to show how the caching works in Drupal 8, but you can use the same thing for any rendered array.

You can disable a block cache in two different ways. You can either use the UncacheableDependencyTrait trait:

<?php

namespace Drupal\test_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\UncacheableDependencyTrait;

/**
 * Provides a 'Test block' Block.
 *
 * @Block(
 *   id = "test_block",
 *   admin_label = @Translation("Test block"),
 *   category = @Translation("Test block"),
 * )
 */
class TestBlock extends BlockBase {

  use UncacheableDependencyTrait;

  public function build() {
    return [
      '#markup' => $this->t('Time is: ') . time(),
    ];
  }

}

or you can set the cache max-age like this:

<?php

namespace Drupal\test_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a 'Test block' Block.
 *
 * @Block(
 *   id = "test_block",
 *   admin_label = @Translation("Test block"),
 *   category = @Translation("Test block"),
 * )
 */
class TestBlock extends BlockBase {

  public function build() {
    return [
      '#markup' => $this->t('Time is: ') . time(),
      '#cache' => [
        'max-age' => 0,
      ]
    ];
  }

}

If you don't want to completely disable the cache for a block, you can use the cache contexts. For example, you can use the user cache context. By using this cache context you will cache the block for each user. This makes sense if the block content is unique to each user. You can see the full list of available cache contexts here.

<?php

namespace Drupal\test_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a 'Test block' Block.
 *
 * @Block(
 *   id = "test_block",
 *   admin_label = @Translation("Test block"),
 *   category = @Translation("Test block"),
 * )
 */
class TestBlock extends BlockBase {

  public function build() {
    $email = \Drupal::currentUser()->getEmail();

    return [
      '#markup' => $this->t('Your email is: ') . $email,
      '#cache' => [
        'contexts' => [
          'user',
        ],
      ]
    ];
  }

}

And the last thing that I want to show you are cache tags. Let's say that a block content depends on the specific node. You want to make sure that each time the node is updated, that block cache will be invalidated. You can do that like this:

<?php

namespace Drupal\test_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provides a 'Test block' Block.
 *
 * @Block(
 *   id = "test_block",
 *   admin_label = @Translation("Test block"),
 *   category = @Translation("Test block"),
 * )
 */
class TestBlock extends BlockBase {

  public function build() {
    $node = \Drupal\node\Entity\Node::load(1);
    $node_title = $node->getTitle();

    return [
      '#markup' => $this->t('The title of node #1 is: ') . $node_title,
      '#cache' => [
        'tags' => ['node:1'],
      ]
    ];
  }

}

IMPORTANT NOTE: all this applies only for logged in users! Next time we'll see how caching works for anonymous users.

If I can be of assistance, please do not hesitate to contact me.

About the author

Goran Nikolovski is a highly experienced Drupal developer with an extensive skill set that includes PHP, MySQL, HTML, CSS and Javascript. He has experience with large Drupal sites and Drupal Commerce 2.x integration, and he is author of several Drupal modules.