Программно визуализировать блок в шаблоне ветки

28

Мне нужно визуализировать блок представлений в моем шаблоне page.html.twig. В D7 я бы сделал это:

<?php
  $block = module_invoke('module_name', 'block_view', 'block_delta');
  print render($block['content']);
?>

В Drupal 8 module_invoke устарел и рекомендуется использовать это: (я добавил имя блока в качестве второго параметра)

Drupal::moduleHandler()->invoke($block, 'views_block__blog_block_1', $args = array());

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

Затем я вызвал функцию в функции preprocess_page () в файле .theme, но прежде чем я смог заставить ее работать, я попытался сделать что-то попроще, просто попытаться заставить переменную работать внутри шаблона ветки, который тоже не работал, например:

В функции template_preprocess_page (& $ vars) в файле .theme:

$test = 'Hello World';
$vars['$my_var'] = $test;

Я попытался вызвать my_var внутри шаблона ветки, но он не сработал, и я получил сообщение об ошибке «Сайт имеет ошибку, пожалуйста, свяжитесь с администратором»

Итак, подведем итог, вот мои вопросы:

  1. Как сделать переменные доступными внутри шаблонов веточек?
  2. Как вызвать функции внутри шаблонов веточек?
  3. Отображать ли блоки внутри файла .theme или шаблона ветки?
Рик Бергманн
источник

Ответы:

47

Вы находитесь на неправильном пути с module_invoke (). Это просто необычный способ вызова функции {$ module_name} _block_view ().

Факт, что это изменилось, не имеет значения, дело в том, что система блоков полностью изменилась в 8.x и теперь использует плагины и объекты конфигурации, эти функции больше не существуют.

У вас есть несколько вариантов.

а) Повторно использовать существующий объект конфигурации блока и просмотреть его. Очень просто, но требует, чтобы такая конфигурация существовала, например, как отключенный блок.

$block = \Drupal\block\Entity\Block::load('your_block_id');
$variables['block_output'] = \Drupal::entityTypeManager()
  ->getViewBuilder('block')
  ->view($block);

б) Создайте экземпляр блочного плагина напрямую, передайте ему конфигурацию (вы можете легко найти идентификатор и конфигурацию блочного плагина в экспортированном объекте конфигурации блока). Недостатком является то, что вы не получаете кэширование рендеринга, но если вы отображаете его где-то, что уже кэшировано (например, шаблон узла), это не имеет значения.

$variables['block_output'] = \Drupal::service('plugin.manager.block')
  ->createInstance($plugin, $configuration)
  ->build();

в) В случае представления вы также можете загрузить представление напрямую и отобразить его.

d) Вы также можете полностью переосмыслить свой подход и использовать регионы блоков или Page Manager (который использует стандартные блочные плагины в 8.x).

Berdir
источник
Спасибо за ваш ответ. Я хотел бы пойти с A или B. Регион будет работать, но я хочу избегать использования региона. Единственная проблема, с которой я сталкиваюсь, - это когда я вызываю block_output в шаблоне ветки, у меня появляется ошибка - «неожиданное имя тега» block_output », поэтому я не знаю, как сделать эту переменную доступной, даже если я создал ее в функции preprocess_page. Я постараюсь решить это
Рик Бергманн
Похоже, вы используете {%? Используйте {{block_output}}.
Бердир
Да, так и было! Все еще пытаюсь освоить веточку. Спасибо.
Рик Бергманн
Начиная с Drupal 8.0.0 entityManager устарел. Вместо этого используйте entityTypeManager .
Филипп Майкл
куда мне поместить этот код? $ block = \ Drupal \ block \ Entity \ Block :: load ('your_block_id'); $ variable ['block_output'] = \ Drupal :: entityManager () -> getViewBuilder ('block') -> view ($ block); Спасибо!
11

В Drupal 8 это работает для рендеринга блочного плагина (то есть того, который вы создали в пользовательском модуле) в preprocess_hook:

function mymodule_preprocess_something(array &$variables) {
  $customblock = \Drupal::service('plugin.manager.block')->createInstance('my_custom_block', []);
  $variables['content']['custom_block_output'] = $customblock->build();
}

Затем вы можете отобразить его в своем шаблоне ветки следующим образом:

{{ content.custom_block_output }}

Примечание: это загрузит общую версию вашего блока. Если вы хотите загрузить экземпляр вашего блока переменными (после того, как вы создали его в / admin / structure / block), вы должны загрузить его следующим образом:

    // Load Instance of custom block with variables
    $example_block = \Drupal::entityManager()->getStorage('block')->load('example_block_machine_name');
    if (!empty($example_block)){
      $example_block_content = \Drupal::entityManager()
        ->getViewBuilder('block')
        ->view($example_block);
      if ($example_block_content) {
        // Add block content to build array
        $variables['content']['custom_block_output'] = $example_block_content;
      }
    }
oknate
источник
1
Это было решение для меня и, безусловно, самое простое.
Гийом Буа