ノードのフィールドをブロック内にレンダリングしたい。それはこのように動作します:
<?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%ではなく、フィールドを通常どおりにレンダリングして、表示モードの設定で表示できるようにするものです。
ビューモードはフィールドではなくノードに適用する必要があると思います。したがって、ビュービルダーを取得してノードをレンダリングする必要があります。その後、ノードのレンダリング配列からフィールドのレンダリング配列を選択できます。このようなもの:
$vb = [EntityTypeManager]->getViewBuilder('node'); // Drupal\node\NodeViewBuilder
$nodeview = $vb->view($node, $viewmode);
$fieldrenderarray = $nodeview[youfield-here];
追伸とにかく、@ [EntityTypeManager]を@ entity_type.managerサービスとして挿入する必要があります。または、$ container-> get( 'entity_type.manager')のBlock-Plugin create()で取得します。
表示モードの表示設定で単一のフィールドをレンダリングするには、フィールドのview()
メソッドを使用できます。
ティーザー形式で画像をレンダリングする例:
$build['image'] = $node->field_image->view('teaser');
または体全体:
$build['body'] = $node->body->view('full');
この答えは 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
_
おかげで 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
を使用すると、必要なフィールドを個別にレンダリングできます。表示モードの設定に応じてキャッシュを追加する方法を見つける必要がありますが、これは別の質問です:)
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セットアップから任意のフィールドをレンダリングする方がおそらく良いでしょうが、どの方法が最適であるかは、特定のユースケースに本当に依存すると思います。