web-dev-qa-db-fra.com

Comment puis-je rendre par programmation le champ d'un nœud en respectant les paramètres du mode d'affichage?

Je veux rendre le champ d'un nœud à l'intérieur d'un bloc. Cela fonctionne comme ceci:

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

Mais ce n'est pas 100% comme si je rendais simplement le champ normalement, le rendant visible dans les paramètres du mode d'affichage.

9
Alex

Je pense que le mode d'affichage devrait être appliqué au nœud, pas au champ. Vous devez donc obtenir le générateur de vues et rendre le nœud. Ensuite, vous pouvez choisir le tableau rendu pour le champ dans le tableau de rendu node'r. Un peu comme ça:

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

P.S. Vous devez de toute façon "[EntityTypeManager]" injecté en tant que service @ entity_type.manager. Ou récupérez-le dans votre Block-Plugin create () à partir de $ container-> get ('entity_type.manager').

0
Rainer Feike

Pour rendre un champ unique avec le paramètre d'affichage d'un mode d'affichage, vous pouvez utiliser la méthode view() du champ:

Exemple de rendu d'image au format teaser:

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

Ou le corps en entier:

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

Cette réponse s'appuie sur 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);

Pour rendre complètement par programmation le champ que vous terminez en appelant renderRoot(), qui établit un contexte de rendu distinct de ce que les réponses de page typiques utiliseraient - un seul contexte de rendu pour une demande ou une sous-demande. Nous pourrions également utiliser renderPlain(), mais cela échapperait à tout.

Dans la réponse Drush mais pas dans l'exécution de page normale, cela m'a lancé un avertissement:

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

Merci à réponse de Rainer Feike Je suis arrivé à la solution:

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

}

En utilisant $viewBuilder->viewField Je peux rendre séparément tous les champs dont j'ai besoin. J'ai juste besoin de savoir comment ajouter la mise en cache en fonction des paramètres du mode d'affichage, mais c'est une autre question :)

2
Alex

lié à la réponse de Alex , voici comment je l'ai modifié pour utiliser config_pages et construire un bloc 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;

}

Il est probablement préférable de restituer des champs arbitraires à partir d'une configuration config_pages plutôt que d'extraire des données d'un nœud, mais je suppose que cela dépend vraiment du cas d'utilisation spécifique de la méthode la plus appropriée.

2
bdanin