Drupal 8 - Добавить пользовательский контекст кеша - PullRequest
0 голосов
/ 21 января 2019

У меня следующая ситуация: я хочу скрыть или показать некоторые локальные задачи (вкладки) на основе поля текущего пользователя.Поэтому я реализовал hook_menu_local_tasks_alter() in my_module/my_module.module:

function my_module_menu_local_tasks_alter(&$data, $route_name, \Drupal\Core\Cache\RefinableCacheableDependencyInterface &$cacheability) {
  ... some logic ...

  if ($user->get('field_my_field')->getValue() === 'some value')
    unset($data['tabs'][0]['unwanted_tab_0']);
    unset($data['tabs'][0]['unwanted_tab_1']);

  ... some logic ...
}

Это прекрасно работает, но мне нужно очистить кеш, если значение field_my_field изменится.

Итак, я обнаружил, что мне нужнореализовать контекст Cache как это в моем my_module_menu_local_tasks_alter:

$cacheability
  ->addCacheTags([
    'user.available_regions',
  ]);

Я определил свой контекст Cache следующим образом:

my_module/my_module.services.yml:

services:
  cache_context.user.available_regions:
    class: Drupal\my_module\CacheContext\AvailableRegions
    arguments: ['@current_user']
    tags:
      - { name: cache.context }

my_module/src/CacheCotext/AvailableRegions.php:

<?php

namespace Drupal\content_sharing\CacheContext;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Session\AccountProxyInterface;

/**
* Class AvailableRegions.
*/
class AvailableRegions implements CacheContextInterface {

  protected $currentUser;

  /**
   * Constructs a new DefaultCacheContext object.
   */
  public function __construct(AccountProxyInterface $current_user) {
    $this->currentUser = $current_user;
  }

  /**
  * {@inheritdoc}
  */
  public static function getLabel() {
    return t('Available sub pages.');
  }

  /**
  * {@inheritdoc}
  */
  public function getContext() {
    // Actual logic of context variation will lie here.
    $field_published_sites = $this->get('field_published_sites')->getValue();

    $sites = [];
    foreach ($field_published_sites as $site) {
      $sites[] = $site['target_id'];
    }

    return implode('|', $sites);
  }

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

}

Но каждый раз, когда я изменяю значение своего поля field_my_field Мне все еще нужно очищать кеши, поэтому контекст не работает.Может ли кто-нибудь указать мне правильное направление, как решить эту проблему или как отладить такого рода Thigs?

1 Ответ

0 голосов
/ 24 января 2019

Вместо предоставления пользовательского контекста кеша, вы должны иметь возможность использовать кешируемость по умолчанию, предоставляемую ядром. Я полагаю, что проблема заключается не столько в создании кешируемых метаданных, сколько в том, что ваш hook_menu_local_tasks_alter изменяет контент, который не знает, что теперь зависит от пользователя. Поэтому я считаю, что вам нужно 2 вещи:

  1. Общий контекст кеша, который говорит, что «это содержимое меню теперь зависит от пользователя», например. user контекст кеша.
  2. Дополнительное использование тега кеша для конкретного пользователя, чтобы сказать: «как только это будет кешировано, когда этот пользовательский объект изменяется, иди регенерируй локальные задачи для этого пользователя».

Обратите внимание, что HOOK_menu_local_tasks_alter предоставляет помощник для кеширования, третий параметр $cacheability. Ядро Drupal также предоставляет здесь механизм, который позволяет нам сказать, что «эта часть данных кэша зависит от этой другой части данных кэша».

Таким образом, вы должны быть в состоянии сделать что-то вроде:

function my_module_menu_local_tasks_alter(&$data, $route_name, RefinableCacheableDependencyInterface &$cacheability) {
  ... some logic ...

  // We are going to alter content by user.
  $cacheability->addCacheableDependency($user);

  // Note if you still really need your custom context, you could add it.
  // Also note that any user.* contexts should already be covered above.
  $cacheability->addCacheContexts(['some_custom_contexts']);

  if ($user->get('field_my_field')->getValue() === 'some value')
    unset($data['tabs'][0]['unwanted_tab_0']);
    unset($data['tabs'][0]['unwanted_tab_1']);

  ... some logic ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...