보기 모드 설정을 기준으로 노드 필드를 프로그래밍 방식으로 렌더링하려면 어떻게해야합니까?


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

뷰 모드는 필드가 아닌 노드에 적용되어야한다고 생각합니다. 따라서 뷰 빌더를 가져 와서 노드를 렌더링해야합니다. 그런 다음 노드의 렌더 배열에서 필드에 대해 렌더링 된 배열을 선택할 수 있습니다. 이런 종류의 :

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

추신 : @ entity_type.manager 서비스로 삽입 된 "[EntityTypeManager]"가 필요합니다. 또는 $ container-> get ( 'entity_type.manager')에서 Block-Plugin create ()로 가져 오십시오.


1
좀 빠지는. $nodeview#node키로
알렉스

1
또한 이것은 별도의 필드가 아닌 노드를 렌더링합니다.
Alex

1
예, 노드 (및 모든 필드)를 렌더링합니다. 그러나 이것은보기 모드 설정에서 조정하는 것입니다. 어쩌면 당신의 질문이 잘못되었을 수도 있습니다.
Rainer Feike

1
"$ nodeview [youfield-here];" 최소 Drupal 8.6.x
Onkeltem

1
"yourfield-here"를 필드의 기계 이름으로 바꾸십시오.
Rainer Feike

29

보기 모드의 표시 설정으로 단일 필드를 렌더링하려면 필드의 view()방법을 사용할 수 있습니다 .

티저 형식으로 이미지를 렌더링하는 예 :

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

또는 몸 전체 :

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

1
불행히도 이것은 레이블 및 포맷터 설정과 같은보기 모드 설정을 존중하지 않습니다.
Alex

1
이것은 작동해야 하며이 명령으로 나뭇 가지 디버그를 사용할 수도 있습니다. 기존보기 모드를 문자열로 제공하면 필드가이 형식으로 지정됩니다. 배열을 제공하면 다음과 같은 고유 한 디스플레이 설정을 지정할 수 있습니다.['label' => 'inline' ]
4k4

1
나는 이미 그것을 시도했지만 작동하지 않았다고 생각합니다. 다시 해 볼게요. 지금까지 감사합니다
Alex

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 repl에서 정상적인 페이지 실행은 아니지만 경고 메시지가 표시됩니다.

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

Alex 의 답변 과 관련하여 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

Rainer Feike의 답변 덕분에 해결책을 찾았습니다 .

<?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필요한 모든 필드를 별도로 렌더링 할 수 있습니다. 보기 모드 설정에 따라 캐싱을 추가하는 방법을 찾아야하지만 이것은 또 다른 질문입니다. :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.