Як я можу програмно зобразити поле вузла з урахуванням налаштувань режиму перегляду?


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%, як якщо б я просто відображав поле нормально, роблячи його видимим у налаштуваннях режиму перегляду.

Відповіді:


0

Я думаю, що viewmode слід застосовувати до вузла, а не до поля. Тож вам потрібно отримати конструктор перегляду та вивести вузол. Згодом ви можете вибрати виведений масив для поля з масиву візуалізації node'r. Такого роду:

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

PS Вам потрібно "[EntityTypeManager]" все-таки ввести як сервіс @ entit_type.manager. Або отримати його у своєму Block-Plugin create () з $ container-> get ('entit_type.manager').


1
не зовсім. $nodeviewє #nodeключовим
Алекс

1
також це робить вузол, а не окремі поля
Алекс

1
Так, я виводить вузол (і всі поля). Але це налаштування в режимі перегляду. Можливо, я неправильно зрозумів ваше запитання.
Райнер Фейке

1
"$ nodeview [youfield-here];" є нульовим, принаймні на Drupal 8.6.x
Onkeltem

1
Замініть "ваше поле-тут" на ім'я машини вашого поля.
Райнер Фейке

29

Щоб візуалізувати одне поле з налаштуваннями відображення режиму перегляду, ви можете скористатися view()методом поля:

Приклад візуалізації зображення у тизерному форматі:

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

Або тіло в повному обсязі:

$build['body'] = $node->body->view('full');

1
на жаль, це не поважає налаштування режиму перегляду, як-от мітки та параметри форматера
Алекс

1
Це повинно працювати, ви навіть можете використовувати налагодження гілочки з цією командою. Якщо ви надаєте існуючий режим перегляду у вигляді рядка, це поле буде відформатоване. Якщо ви надаєте масив, ви можете надати власні налаштування дисплея, наприклад['label' => 'inline' ]
4k4

1
Я вірю, що я вже намагався, але це не спрацювало. я спробую ще раз. дякую поки що
Алекс

1
Я вважаю, що він поважає формат, але не його параметри. Вихід цього включає правильні налаштування.
Грейсайд

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

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, на відміну від витягування даних з вузла, але я думаю, це дійсно залежить від конкретного випадку використання щодо того, який метод найкращий.


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я можу відображати будь-які потрібні поля окремо. Мені просто потрібно дізнатися, як додати кешування залежно від налаштувань режиму перегляду, але це вже інше питання :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.