如何以编程方式呈现尊重视图模式设置的节点字段?


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%,就好像我只是正常渲染该字段一样,使它在查看模式设置中可见。

Answers:


0

我认为viewmode应该应用于节点,而不是字段。因此,您需要获取viewbuilder并渲染该节点。之后,您可以从节点的渲染数组中为字段选择渲染数组。有点像这样:

$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关键
亚历

1
同样,这将呈现节点,而不是单独的字段
Alex

1
是的,我渲染了节点(及其所有字段)。但这是您在查看模式设置中进行的调整。也许我把你的问题弄错了。
Rainer Feike

1
“ $ nodeview [youfield-here];” 为null,至少在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
这应该可行,您甚至可以在此命令中使用twig debug。如果您以字符串形式提供现有的查看模式,则字段将以此格式设置。如果提供阵列,则可以提供自己的显示设置,例如['label' => 'inline' ]
4k4 '16

1
我相信我已经尝试过了,但是没有用。我会再试一次。到目前为止,非常感谢
Alex

1
我发现它尊重格式化程序,但不尊重格式化程序设置。此输出包括正确的设置。
Grayside '17

2
这基本上使我得到了答案,可以在.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副本中,但在正常页面执行中却没有,这对我发出了警告:

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我”可以分别渲染所需的任何字段。我只需要了解如何根据视图模式设置添加缓存,但这是另一个问题:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.