Recently, while working on a project I had to build a block to show the user information of the currently logged-in user. Although it's a straight forward thing to do, the important thing to consider here is caching. Setting the cache max-age to 0 have performance impacts if the block has to be shown on all pages. So, the block has to leverage Drupal's Cache API to have a performant block with proper caching.

Caching the block

Since, the block needs to show the current logged in user information so the cache tags had to be set for user ID of the logged-in user with a context of user. But, for an anonymous user since there will be user ID so, the block will just return the parent cache context i.e ContextAwarePluginBase which is extended by BlockBase.


namespace Drupal\drupal_block_demo\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Link;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\user\UserStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

 * Provides an example block.
 * @Block(
 *   id = "drupal_block_demo_example",
 *   admin_label = @Translation("User info"),
 *   category = @Translation("Drupal block demo")
 * )
class ExampleBlock extends BlockBase implements ContainerFactoryPluginInterface {

   * @var \Drupal\Core\Session\AccountProxyInterface
  protected $currentUser;

   * @var \Drupal\user\UserStorageInterface
  protected $userStorage;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccountProxyInterface $current_user, UserStorageInterface $user_storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->currentUser = $current_user;
    $this->userStorage = $user_storage;

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(

  protected function getUser() {
    if ($this->currentUser->id() === 0) {
      return FALSE;
    $user = $this->userStorage->load($this->currentUser->id());
    return $user;

  public function build() {
    $build['content'] = [
      '#markup' => $this->getUser() ? $this->getUser()->label() : Link::createFromRoute($this->t('Log in'), 'user.login')->toString(),
    return $build;

  public function getCacheContexts() {
    return Cache::mergeContexts(parent::getCacheContexts(), ['user']);

  public function getCacheTags() {
    if ($user = $this->getUser()) {
      return Cache::mergeTags(parent::getCacheTags(), ['user', $user->id()]);
    return parent::getCacheTags();