Переменные, введенные или установленные в файле Twig, не определены после первой позиции поля ссылки на сущность
У меня есть настройка абзаца, в которой есть поле ссылки на сущность, позволяющее редактору выбирать несколько узлов для использования в отображении.
Основываясь на количестве узлов, я хочу запустить класс. Я решил, что способ сделать это - использовать hook_preprocess_node()
в теме:
$referringItem = $node->_referringItem;
if (!empty($referringItem)) {
$referringEntity = $referringItem->getEntity();
if (
!empty($referringEntity)
&& ($referringEntity instanceof NodeInterface || $referringEntity instanceof Paragraph)
) {
$referringEntityType = $referringEntity->getType();
$referringEntityTypeId = $referringEntity->getEntityTypeId();
}
}
if ($referringEntityType == 'homepage_feature') {
$count = $referringEntity->get('field_items')->count();
// Default.
$variables['top_image'] = FALSE;
$variables['right_image'] = FALSE;
// Should this be count is only 1 AND it is the first delta item in field_feature?
// If not, any single item Homepage Feature will get top-image which may not be
// desired.
if ($count == 1) {
$variables['top_image'] = TRUE;
}
}
Приведенная выше логика может быть слишком сложной. В основном я оглядываюсь назад, чтобы посмотреть, какой тип абзаца использовался, чтобы я мог передать новые переменные в шаблон.
Что я заметил, так это то, что, хотя код выполняется для каждого указанного узла, переменные существуют только в первом узле. Я сбросил их в шаблон, и там все правильно, но они не определены в других узлах.
В Twig я попытался сбросить переменную в верхней части шаблона:
{{ top_image }}
Я вижу это в первой записи 1
над разметкой, а затем она больше никогда не отображается.
Как я могу гарантировать, что переменные передаются в шаблон правильно, каждый время?
Редактировать:
Похоже, что использование одного и того же узла с одинаковым режимом просмотра в разных абзацах или ссылках на сущности на одной и той же странице может привести к этому.
Является ли тогда решением добавить теги/контекст кэша к отображаемому узлу, чтобы учесть, какой родитель выводит его?
1 answers
Основываясь на комментариях к вопросу, я расширил класс EntityReferenceEntityFormatter
и изменил одну часть в методе viewElements
(остальное то же самое):
$view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
$elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
try {
$parent = $items->getParent();
$parent_entity = $parent->getValue();
$elements[$delta]['#cache']['keys'][] = $parent_entity->id();
$elements[$delta]['#cache']['keys'][] = $parent_entity->bundle();
$elements[$delta]['#cache']['keys'][] = $parent_entity->getEntityTypeId();
$elements[$delta]['#cache']['keys'][] = 'context_aware';
// Add special information for different paragraph types.
if ($parent_entity->getEntityTypeId() == 'paragraph') {
if ($parent_entity->bundle() == 'homepage_feature') {
$elements[$delta]['#style_flags']['top_image'] = FALSE;
$elements[$delta]['#style_flags']['right_image'] = FALSE;
if ($parent_entity->get('field_items')->count() === 1) {
$elements[$delta]['#style_flags']['top_image'] = TRUE;
}
}
}
} catch (\Exception $e) {
// Add logging
}
Позже, в разделе preprocess_node:
// ONLY for the homepage handling of featured content.
if ($referringEntityType == 'homepage_feature') {
$variables['top_image'] = $variables['elements']['#style_flags']['top_image'];
$variables['right_image'] = $variables['elements']['#style_flags']['right_image'];
}
Затем я смог добавить один и тот же узел в один и тот же тип абзаца несколько раз с правильной информацией. Теперь применяются правильные классы.
Изменить:
Просто чтобы добавить к этому, обязательно установите свои кэшируемые зависимости, чтобы любые изменения содержали ссылки не потребует очистки кэша:
$parent = $items->getParent();
$entity->addCacheableDependency($parent);
Правка 2:
Благодаря дополнительному руководству от 4k4 я ввел сервис визуализации и сократил его до:
$parent = $items->getParent();
$parent_entity = $parent->getValue();
$elements[$delta]['#cache']['keys'][] = $parent_entity->id();
$elements[$delta]['#cache']['keys'][] = $parent_entity->bundle();
$elements[$delta]['#cache']['keys'][] = $parent_entity->getEntityTypeId();
$elements[$delta]['#cache']['keys'][] = 'context_aware';
if ($this->paragraphDisplaySettings->isApplicable($parent_entity)) {
$elements[$delta]['#style_flags'] = $this->paragraphDisplaySettings->getSettings($parent_entity);
}
$this->renderer->addCacheableDependency($elements[$delta], $parent);
paragraphDisplaySettings
это объект настраиваемой службы, который помогает оценивать различные флаги, передаваемые из исходного кода, просто для того, чтобы он был чище и компактнее. Это отлично работает.