Как передать переменную темы из шаблона в другой?


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

У меня есть тема, в которой есть функции предварительной обработки как для тела информационного бюллетеня, так и для полей, содержащихся в теле.

Я хочу установить переменную в теле функция предварительной обработки и связанный с ней шаблон ветки, который может быть проверен функцией предварительной обработки поля и/или ее собственным шаблоном.

Другими словами, я хочу, чтобы каждое поле было осведомлено о контексте тела, в котором оно отображается.

В частности, у меня есть mytheme_preprocess_simplenews_newsletter_body(), который задает переменную ($variables['summons'] = 'placeholder';), которую можно проверить (а также установить) с помощью шаблона simplenews-newsletter-body.html.twig темы, но (поскольку он находится в другом массиве визуализации) впоследствии не отображается для mytheme_preprocess_field() ни поле --узел--заголовок.html.ветка.

Как мне взаимодействовать между двумя массивами рендеринга?

Обратите внимание, что

  1. По-видимому, существуют глобальные переменные, такие как $db_is_active и $is_admin.

  2. Иногда этого можно добиться, каскадируя атрибуты CSS-класса из содержащего элемента в содержащийся элемент. Это в целом неудовлетворительно, и в данном конкретном случае это не будет работать на разных целевых почтовых клиентах непредсказуемое лечение CSS.

Author: kiamlaluno, 2016-01-13

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;
}

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

 4
Author: iainH, 2016-01-15 12:29:12

Я использую этот код:

/**
 * 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();
}
 1
Author: Adrian Cid Almaguer, 2017-01-18 14:31:34

Я все еще новичок в D8, так что я легко могу упустить какой-нибудь трюк. Как правило, в этой ситуации вы хотите найти наиболее конкретный крючок, который даст вам доступ ко всему, что вы хотите изменить. Таким образом, изменение на уровне поля слишком специфично, а на уровне страницы (например) - слишком общее.

К сожалению, MailEntity не является реальной сущностью (Drupal), поэтому вы не можете использовать стандартные крючки для изменения ее массива визуализации. Он не вызывает никаких пользовательских крючков, которые я вижу, чтобы позволить вам изменять содержимое любой. В D7 в этой ситуации у меня был бы соблазн использовать hook_page_alter(), который грязен, но, я думаю, сработал бы, но он был удален из D8.

Вы всегда можете переопределить класс MailEntity и предоставить свои собственные настройки непосредственно там, но необходимость делать это для изменений темы кажется мне немного неправильной.

 0
Author: Andy, 2016-01-15 19:15:07