Как передать переменную темы из шаблона в другой?
Несколько полей в узле должны отображаться определенным образом в зависимости от того, частью какого тела информационного бюллетеня они являются. Как мне передать переменную из вложенного тела информационного бюллетеня в вложенные поля, чтобы я мог информировать поле о его контексте и контролировать способ отображения поля?
У меня есть тема, в которой есть функции предварительной обработки как для тела информационного бюллетеня, так и для полей, содержащихся в теле.
Я хочу установить переменную в теле функция предварительной обработки и связанный с ней шаблон ветки, который может быть проверен функцией предварительной обработки поля и/или ее собственным шаблоном.
Другими словами, я хочу, чтобы каждое поле было осведомлено о контексте тела, в котором оно отображается.
В частности, у меня есть mytheme_preprocess_simplenews_newsletter_body()
, который задает переменную ($variables['summons'] = 'placeholder';
), которую можно проверить (а также установить) с помощью шаблона simplenews-newsletter-body.html.twig темы, но (поскольку он находится в другом массиве визуализации) впоследствии не отображается для mytheme_preprocess_field()
ни поле --узел--заголовок.html.ветка.
Как мне взаимодействовать между двумя массивами рендеринга?
Обратите внимание, что
По-видимому, существуют глобальные переменные, такие как
$db_is_active
и$is_admin
.Иногда этого можно добиться, каскадируя атрибуты CSS-класса из содержащего элемента в содержащийся элемент. Это в целом неудовлетворительно, и в данном конкретном случае это не будет работать на разных целевых почтовых клиентах непредсказуемое лечение CSS.
3 answers
Решение, с которым я работаю, заключается в использовании drupal_static()
; упрощенные основы в приведенном ниже коде - будьте осторожны с &амперсандами. Это дает мне контроль там, где мне это нужно.
Таким образом, используя этот подход, я могу - с учетом их глобального контекста - для каждого поля устанавливать переменные обычным способом, например, в mytheme_preprocess_field()
, которые впоследствии будут использоваться в соответствующем шаблоне, таком как field--node--title--agenda.html.twig
function mytheme_preprocess_simplenews_newsletter_body(&$variables) {
// prepare to alter static var ...
// get a reference binding to static var
$var = &myvariable_function();
// alter static var
$var = 'simplenews_newsletter';
}
function mytheme_preprocess_field(&$variables, $hook) {
// prepare to read static var
// assign static var
$var = myvariable_function();
// $element is the render array for the field
$element = $variables['element'];
// filter those cases where it matters that we're theming a newsletter
if ($element['#view_mode'] == 'email_html' and $var == 'simplenews_newsletter') {
// Do stuff here like setting a variable for twig ...
$variables['summons'] = 'some text';
}
}
function &myvariable_function() {
$var = &drupal_static(__FUNCTION__);
if (!isset($var)) {
// generate contents of static variable
$var = 'initial_value';
}
return $var;
}
Я уверен, что существуют другие способы передачи общего контекста между различными уровнями иерархия визуализации страницы. Дайте мне знать, как бы вы это сделали.
Я использую этот код:
/**
* Helper function to pass slider variables from preprocess_page to preprocess_page_title_custom
* @param string $new_image Image URL
* @return array Images URL Array
*/
function _core_slider_images($new_image = NULL) {
$vars = &drupal_static(__FUNCTION__, array());
// If a new value has been passed add to the array.
if ($new_image) {
$vars[] = $new_image;
}
return $vars;
}
Из этого шаблона:
В page.html.twig
у нас есть доступ к переменной $node
, и нам нужно передать значения в другой шаблон, у которого нет доступа к этой переменной. Мы будем искать значения, которые нам нужно передать, и вызывать _core_slider_images()
, эта функция будет мостом между двумя шаблонами (функциями предварительной обработки)
/**
* Implements hook_preprocess_page().
*/
function MODULE_preprocess_page(&$variables) {
// ...
// Sending Images URL and titles from page to page_title.
for ($i = 0; $i < $cant; $i++) {
// Adding the images to the static function.
_core_slider_images($variables['node']->field_image[$i]->entity->url());
}
}
К этому шаблону:
page-title-custom.html.twig
является пользовательским шаблоном и не имеет доступа к $node
. Как hook_preprocess_page()
называется сначала мы сохранили значения $node
в статическом var, и нам нужно только вызвать функцию _core_slider_images()
.
/**
* Implements hook_preprocess_HOOK().
*/
function MODULE_preprocess_page_title_custom(&$variables) {
// Searching the variables for sending to the page-title-custom template.
$images = _core_slider_images();
}
Я все еще новичок в D8, так что я легко могу упустить какой-нибудь трюк. Как правило, в этой ситуации вы хотите найти наиболее конкретный крючок, который даст вам доступ ко всему, что вы хотите изменить. Таким образом, изменение на уровне поля слишком специфично, а на уровне страницы (например) - слишком общее.
К сожалению, MailEntity
не является реальной сущностью (Drupal), поэтому вы не можете использовать стандартные крючки для изменения ее массива визуализации. Он не вызывает никаких пользовательских крючков, которые я вижу, чтобы позволить вам изменять содержимое любой. В D7 в этой ситуации у меня был бы соблазн использовать hook_page_alter()
, который грязен, но, я думаю, сработал бы, но он был удален из D8.
Вы всегда можете переопределить класс MailEntity
и предоставить свои собственные настройки непосредственно там, но необходимость делать это для изменений темы кажется мне немного неправильной.