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

9

Я хочу визуализировать поле узла внутри блока. Это работает так:

<?php

if ($node) {
  if (isset($node->field_body_secondary) && $field = $node->field_body_secondary->value) {
    $markup = render($field);
    $build = array(
      '#type' => 'markup',
      '#markup' => $markup,
    );
  }
}

return $build;

Но это не 100%, как если бы я просто отображал поле в обычном режиме, делая его видимым в настройках режима просмотра.

Alex
источник

Ответы:

0

Я думаю, что режим просмотра должен применяться к узлу, а не к полю. Итак, вам нужно получить viewbuilder и визуализировать узел. После этого вы можете выбрать визуализированный массив для поля из массива рендеринга node'r. Вроде как это:

$vb = [EntityTypeManager]->getViewBuilder('node'); // Drupal\node\NodeViewBuilder
$nodeview = $vb->view($node, $viewmode);
$fieldrenderarray = $nodeview[youfield-here];

PS Вам нужно «[EntityTypeManager]» в любом случае внедрить как сервис @ entity_type.manager. Или получите его в своем блочном плагине create () из $ container-> get ('entity_type.manager').

Райнер Фейке
источник
1
не совсем. $nodeviewимеет в #nodeкачестве ключа
Алекс
1
Кроме того, это делает узел, а не отдельные поля
Alex
1
Да, я визуализирую узел (и все его поля). Но это то, что вы настраиваете в настройках режима просмотра. Может быть, я неправильно понял ваш вопрос.
Райнер Фейке,
1
"$ nodeview [youfield-сюда];" является нулевым, по крайней мере, на Drupal 8.6.x
Onkeltem
1
Замените «yourfield-here» на имя машины вашего поля.
Райнер Фейке
29

Для визуализации отдельного поля с настройкой отображения режима просмотра вы можете использовать view()метод поля:

Пример для рендеринга изображения в формате тизера:

$build['image'] = $node->field_image->view('teaser');

Или тело в полном объеме

$build['body'] = $node->body->view('full');
4k4
источник
1
к сожалению, это не относится к настройкам режима просмотра, таким как метки и настройки форматирования
Alex
1
Это должно работать, вы даже можете использовать отладку ветки с этой командой. Если вы предоставляете существующий режим просмотра в виде строки, поле будет отформатировано с этим. Если вы передадите массив , который вы можете дать свои собственные параметры отображения, например['label' => 'inline' ]
4k4
1
Я думаю, что уже пробовал, но это не сработало. я попробую снова. спасибо до сих пор
Алекс
1
Я считаю, что это уважает форматер, но не настройки форматера. Вывод этого включает в себя правильные настройки.
Grayside
2
это по сути привело меня к ответу, где я могу получить свою переменную в .twig: $vars['var_name'] = $node_object->field_name->view()[0]; и затем в ветке , я могу сделать {{var_name}}
bdanin
4

Этот ответ основан на https://drupal.stackexchange.com/a/208061/394

// Designate the field we want to render.
$field_name = 'body';
// Retrieve a render array for that field with the given view mode.
$render_array = $entity->$field_name->view('full');
// Render the result.
\Drupal::service('renderer')->renderRoot($render_array);

Чтобы полностью программно отобразить поле, вы заканчиваете вызовом renderRoot(), который устанавливает отдельный контекст визуализации из того, что будут использоваться типичные ответы страницы - один контекст визуализации для запроса или подзапроса. Мы могли бы также использовать renderPlain(), но тогда это избежало бы всех вещей.

В реплике Drush, но не в обычном исполнении страницы, это выдало мне предупреждение:

PHP warning:  DOMDocument::loadHTML(): Tag drupal-entity invalid in Entity, line: 1 in /drupal/core/lib/Drupal/Component/Utility/Html.php on line 286
Grayside
источник
2

в связи с ответом Алекса , вот как я изменил его, чтобы использовать config_pages и построить блок global_footer:

<?php

public function build() {
$config_name = 'global_footer';
$config = config_pages_config($config_name);
$build = array();
$markup = array();

$fieldsToRender = array(
  'field_body', 'field_foo', 'field_bar'
);

$viewmode = 'default';
$entityType = 'config_pages';
$display = entity_get_display($entityType, $config_name, $viewmode);
$viewBuilder = \Drupal::entityTypeManager()->getViewBuilder($entityType);

foreach ($fieldsToRender as $field_name) {
  if (isset($config->{$field_name}) && $field = $config->{$field_name}) {
    $fieldRenderable = $viewBuilder->viewField($field, $display->getComponent($field_name));
    if (count($fieldRenderable) &&! empty($fieldRenderable)) {
      $markup[] = \Drupal::service('renderer')->renderRoot($fieldRenderable);
    }
  }
}

if (count($markup)) {
  $build = array(
    '#type' => 'markup',
    '#markup' => implode("", $markup),
  );
}

return $build;

}

Вероятно, лучше визуализировать произвольные поля в настройке config_pages, а не извлекать данные из узла, но я думаю, что это действительно зависит от конкретного варианта использования того, какой метод лучше.

bdanin
источник
2

Благодаря ответу Райнера Фейке я пришел к решению:

<?php

public function build() {
  $node = \Drupal::routeMatch()->getParameter('node');
  $build = array();
  $markup = array();

  $fieldsToRender = array(
    'field_node_ref', 'field_foo', 'field_bar',
  );

  $viewmode = 'default';
  $entityType = 'node';
  $display = entity_get_display($entityType, $node->getType(), $viewmode);
  $viewBuilder = \Drupal::entityTypeManager()->getViewBuilder($entityType);

  foreach ($fieldsToRender as $field_name) {
    if (isset($node->{$field_name}) && $field = $node->{$field_name}) {
      $fieldRenderable = $viewBuilder->viewField($field, $display->getComponent($field_name));
      if (count($fieldRenderable) &&! empty($fieldRenderable)) {
        $markup[] = \Drupal::service('renderer')->renderRoot($fieldRenderable);
      }
    }  
  }

  if (count($markup)) {
    $build = array(
      '#type' => 'markup',
      '#markup' => implode("", $markup),
    );
  }

  return $build;

}

Используя $viewBuilder->viewFieldя могу визуализировать любые поля отдельно мне нужно. Мне просто нужно узнать, как добавить кеширование в зависимости от настроек режима просмотра, но это другой вопрос :)

Alex
источник