Как побороть кэш для конкретного режима отображения

Главные вкладки

Аватар пользователя mnigma mnigma 5 июня 2021 в 0:44

Доброго времени суток.
Прошу помощи. Долго не могу решить проблему кэша.
Для примера Есть материал base. Есть режим отображения для него region. Таксономия в два уровня.

Нужно:

  • при отображении на странице термина "родителя" показывать в ноде только дочерний термин поля "Регион".
  • при отображение на странице дочернего термина - вообще не показывать поле "Регион"

Т.е. Находимся на странице термина Ростовская область - показывается Таганрог: Адрес 1
Находимся на странице Таганрог, вообще скрыть это поле и показывать только Адрес 1

Вывожу страницу термина через tvi

Изначально пробовал через добавление дополнительного шаблона.

function THEME_NAME_theme_suggestions_node_alter(array &$suggestions, array $variables)
{
   $current_path = Drupal::service('path.current')->getPath();
   $path_args = explode('/', $current_path);
    if($path_args[1]=='taxonomy'){
        $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($path_args[3]);
        $parent = $term->parent->target_id;
        if($parent){
            $suggestions[] = 'node__'......
        }else{
            $suggestions[] = 'node__'......
        }
    }
}

Этот же код всовывал и в MODULE_theme_suggestions_node
Но после сброса кэша хуки suggestions повторно не подхватываются - не обрабатываются.

Потом так решил попробовать

function MODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
    if ($entity->bundle() == 'base' && $display->getMode() == 'taksonomiya_region') {
        $current_path = Drupal::service('path.current')->getPath();
        $path = explode('/', $current_path);
        if($path[1]=='taxonomy'){
            $term = Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($path[3]);
            $parent = $term->parent->target_id;
            if($parent){
                unset($build['field_region_base'][1]);
                unset($build['field_region_base'][0]);
            }else{
                $build['field_region_base'][0] = $build['field_region_base'][1];
                unset($build['field_region_base'][1]);
            }
        }

    }
}

Не помогло.

Куда копать? Совсем кэш рубить не хочется (локально в develop без кэша все нормально).

Лучший ответ

Аватар пользователя mnigma mnigma 5 июня 2021 в 13:28

Как оказалось, все очень просто. Хотел сделать на основании данных кук, но они же меняются только при повторной перезагрузке страницы.

$build['#cache']['contexts'][] = 'cookies:my_cookie_name';

Пробовал на основе установки, но что-то не подхватываются..

$build['#cache']['contexts'][] = 'headers:LevelTag';

В общем добавил по url.path

function MODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
    if ($entity->bundle() == 'base' && $display->getMode() == 'taksonomiya_region') {
        $build['#cache']['contexts'][] = 'url.path';
    }
}

P.S. Не знаю как сейчас добавить в заголовок, что РЕШЕНО. Наверно убрали такую возможность.

Комментарии

Аватар пользователя mnigma mnigma 5 июня 2021 в 9:58

Спасибо за ответ! Пробовал

$build['#cache']['max-age'] = 0;
Drupal::service('page_cache_kill_switch')->trigger();

забыл написать - не работает. Чувствую, что где-то рядом хожу, но что-то или не там или не то прописываю.

Нашел https://niklan.net/blog/155 Вроде как кэш даже не нужно отключать, а просто прописать ['#cache']['context'], но пока все равно не работает в таком виде:

use \Symfony\Component\HttpFoundation\Cookie;
use \Symfony\Component\HttpFoundation\Response;
function THEME_preprocess_html(&$vars)
{
$response = new Response();
.........
        if (count($terms) == 1) {
            $cookie = new Cookie('reg_level', 1);
         } else {
            $cookie = new Cookie('reg_level', 2);
         }
        $response->headers->setCookie($cookie);
         $response->send();
}

function MODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
    if ($entity->bundle() == 'fishing_base') {
        $build['#cache']['context'][] = 'cookies:reg_level';
        $build['#cache']['max-age'] = 0;
        Drupal::service('page_cache_kill_switch')->trigger(); # как с этой, так и без нее не работает
    }
}

Сейчас прописал

function THEME_preprocess_node(&$vars){
........
if ($vars['view_mode'] == 'taksonomiya_region') {
     ....
         if(count($variable_terms_page) == 1){
              $vars['count_term']=1;
          }else{
              $vars['count_term']=2;
          }
}
.....
}

В темплейте

{% if count_term == 1 %}
    {{ content.field_region_base.1 }}:
 {% else %}
     ------
  {% endif %}

Аналогично - НЕ работает нужным образом.

Буду еще копать.

Аватар пользователя mnigma mnigma 5 июня 2021 в 10:02

Получается, у меня зависит не от самого содержимого ноды, а от страницы таксономии на которой эта нода находится. Если это страница таксономии родительского термина, то у ноды нужно выводить одно значение, а если страница дочернего термина, то другое.

Аватар пользователя mnigma mnigma 5 июня 2021 в 13:28

Как оказалось, все очень просто. Хотел сделать на основании данных кук, но они же меняются только при повторной перезагрузке страницы.

$build['#cache']['contexts'][] = 'cookies:my_cookie_name';

Пробовал на основе установки, но что-то не подхватываются..

$build['#cache']['contexts'][] = 'headers:LevelTag';

В общем добавил по url.path

function MODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
    if ($entity->bundle() == 'base' && $display->getMode() == 'taksonomiya_region') {
        $build['#cache']['contexts'][] = 'url.path';
    }
}

P.S. Не знаю как сейчас добавить в заголовок, что РЕШЕНО. Наверно убрали такую возможность.