it-swarm.com.de

Wie kann ich das Feld eines Knotens programmgesteuert unter Berücksichtigung der Einstellungen für den Ansichtsmodus rendern?

Ich möchte das Feld eines Knotens innerhalb eines Blocks rendern. Es funktioniert so:

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

Dies ist jedoch nicht 100% ig, als würde ich das Feld nur normal rendern und es in den Einstellungen des Ansichtsmodus sichtbar machen.

9
Alex

Ich denke, der Ansichtsmodus sollte auf den Knoten angewendet werden, nicht auf das Feld. Sie müssen also den Viewbuilder herunterladen und den Knoten rendern. Anschließend können Sie das gerenderte Array für das Feld aus dem Render-Array des Knotens auswählen. Ein bisschen wie das:

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

P.S. Sie müssen sowieso "[EntityTypeManager]" als @ entity_type.manager-Dienst einfügen. Oder holen Sie es sich in Ihrem Block-Plugin create () von $ container-> get ('entity_type.manager').

0
Rainer Feike

Um ein einzelnes Feld mit der Anzeigeeinstellung eines Ansichtsmodus zu rendern, können Sie die Methode view() des Felds verwenden:

Beispiel für das Rendern des Bildes im Teaser-Format:

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

Oder der Körper in vollem Umfang:

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

Diese Antwort baut auf https://drupal.stackexchange.com/a/208061/394 auf

// 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);

Um das Feld vollständig programmgesteuert zu rendern, rufen Sie renderRoot() auf, wodurch ein separater Renderkontext erstellt wird, der von den typischen Seitenantworten abweicht - ein einzelner Renderkontext für eine Anforderung oder Unteranforderung. Wir könnten auch renderPlain() verwenden, aber dann würde es allen Dingen entkommen.

In der Drush-Antwort, aber nicht in der normalen Seitenausführung, warnte mich dies:

PHP warning:  DOMDocument::loadHTML(): Tag drupal-entity invalid in Entity, line: 1 in /drupal/core/lib/Drupal/Component/Utility/Html.php on line 286
4
Grayside

Dank Antwort von Rainer Feike kam ich zur Lösung:

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

}

Verwenden von $viewBuilder->viewField Ich kann alle benötigten Felder separat rendern. Ich muss nur herausfinden, wie man Caching in Abhängigkeit von den Einstellungen des Ansichtsmodus hinzufügt, aber dies ist eine andere Frage :)

2
Alex

im Zusammenhang mit der Antwort von Alex habe ich Folgendes geändert, um config_pages zu verwenden und einen global_footer-Block zu erstellen:

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

}

Es ist wahrscheinlich besser, beliebige Felder aus einem config_pages-Setup zu rendern, als Daten von einem Knoten abzurufen, aber ich denke, es hängt wirklich vom spezifischen Anwendungsfall ab, welche Methode die beste ist.

2
bdanin