表示モードの設定に従ってノードのフィールドをプログラムでレンダリングするにはどうすればよいですか?


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

PSとにかく、@ [EntityTypeManager]を@ entity_type.managerサービスとして挿入する必要があります。または、$ container-> get( 'entity_type.manager')のBlock-Plugin create()で取得します。


1
かなりではありません。鍵として$nodeview持って#nodeいる
Alex

1
また、これにより、個別のフィールドではなくノードがレンダリングされます
Alex

1
はい、ノード(およびそのすべてのフィールド)をレンダリングします。しかし、これはビューモード設定で調整するものです。多分私はあなたの質問を間違えました。
Rainer Feike

1
「$ nodeview [youfield-here];」は、少なくともDrupal 8.6.xではnullです
Onkeltem

1
「yourfield-here」をフィールドのマシン名に置き換えます。
Rainer Feike

28

表示モードの表示設定で単一のフィールドをレンダリングするにview()は、フィールドのメソッドを使用できます。

ティーザー形式で画像をレンダリングする例:

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

または体全体:

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

1
残念ながら、これはラベルやフォーマッター設定などの表示モード設定を尊重しません
Alex

1
これは機能するはずです。このコマンドでtwig debugを使用することもできます。既存の表示モードを文字列として指定すると、フィールドはこれでフォーマットされます。配列を提供する場合は、独自の表示設定を指定できます。たとえば、['label' => 'inline' ]
4k4

1
私はすでにそれを試しましたが、うまくいきませんでした。もう一度やってみます。これまでのところありがとう
Alex

1
私はそれがフォーマッターを尊重しているが、フォーマッター設定を尊重していないことに気づきました。この出力には、正しい設定が含まれています。
グレイサイド2017年

1
これは本質的に私に答えをもたらしました、そこで私は.twigで変数を得ることができます:$vars['var_name'] = $node_object->field_name->view()[0]; そして、twigで、{{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.