1

I created a page using Page Manager with Layout Builder. I created a path called: /my-account/{agent_number} witch allows me to create the agent_number string context. I created my own custom block and able to get the agent_number like this:

$this->getContextValue('agent_number');

Now I build my block and would like to use contexts to cache my block:

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data($this->getContextValue('agent_number'));
  return [
    '#theme' => 'my_custom_module',
    '#data' => $data,
    '#cache' => [
      'contexts' => ['agent_number'],
      'max-age' => 86400,
    ],
  ];
}

I created my own CacheContext service:

<?php

namespace Drupal\earc_card_details\Cache\Context;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;

/**
 * Defines the AgentNumberCacheContext service, for caching.
 *
 * Cache context ID: 'agent_number'.
 *
 * @see \Drupal\Core\Session\AccountProxy::setAccount()
 */
class AgentNumberCacheContext implements CacheContextInterface {

  /**
   * The context repository service.
   *
   * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
   */
  protected $contextRepository;

  /**
   * Creates LanguageInterfaceContext object.
   *
   * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
   *   The context repository service.
   */
  public function __construct(ContextRepositoryInterface $context_repository) {
    $this->contextRepository = $context_repository;
  }

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {
    return t("Agent Number");
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
     $contexts = $this->contextRepository->getAvailableContexts();
     // Agent number is missing here.
     return $contexts['agent_number'] ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }

}

The problem is that $this->contextRepository->getAvailableContexts() does not return the agent_number context. Is there a way to get the page bulder context to appear here?

1

Try a route based context extending RouteCacheContext:

Example:

<?php

namespace Drupal\Core\Cache\Context;

/**
 * Defines the RouteCacheContext service, for "per route name" caching.
 *
 * Cache context ID: 'route.name'.
 */
class RouteNameCacheContext extends RouteCacheContext {

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {
    return t('Route name');
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
    return $this->routeMatch->getRouteName();
  }

}

You can use this core example and get instead of the route name a route parameter.

You can improve cache efficiency and prefix the context name with route.. Cache contexts are ordered hierarchically, so that the caching system can remove specific cache contexts already covered by more general ones when merging cache metadata.

This leads to further considerations. If the block is only visible on a specific route and the route has only one parameter, then the core route context would have the same results as the custom context. So a specific route context only makes sense if you have too many cached block variations because the block is used in different routes or because of other route parameters and the context aware block plugin doesn't have already an appropriate cache context.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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