it-swarm.com.de

Wie rendere ich eine benutzerdefinierte Entität in einem Controller?

Ich habe eine benutzerdefinierte Entität namens foo erstellt. Diese Entität verfügt über ein eindeutiges name -Feld sowie den Standardschlüssel id. Ich möchte eine Seite erstellen, auf der der Benutzer die gerenderte Entität ähnlich wie auf der Administrationsseite sehen kann, aber anstatt sie durch id zu referenzieren, möchte ich name.

Ich habe Folgendes in meinem Controller:

public function content($name) {
  $output = [];
  //Add a couple things to the $output array
  $output['first thing'] = [/*stuff*/];

  $sql = "SELECT id FROM foo WHERE name=:name";
  $sql_params = [':name' => $name];
  $results = db_query($sql, $sql_params)->fetchAll(PDO::FETCH_ASSOC);
  $render_array = [];
  if (count($results) > 0) {
    $id = $results[0]['id'];

    $entity_type = 'foo';
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity_type);
    $controller = \Drupal::entityManager()->getStorage($entity_type);
    $entity = $controller->load($id);
    $build = $view_builder->view($entity);
    $render_array = render($build);
    $output['entity'] = $render_array;
  }
  return $output;
}

Ich erhalte jedoch eine Fehlermeldung: User error: "entity" is an invalid render array key in Drupal\Core\Render\Element::children() (line 97 of core\lib\Drupal\Core\Render\Element.php).

Was muss ich anders machen, damit meine Entität auf der Seite gerendert wird?

2
Kevin Nowaczyk

Controller sollten ein Render-Array (oder eine benutzerdefinierte Antwort) zurückgeben. Sie müssen fast nie selbst etwas außerhalb einer Vorlage rendern.

Ersetzen Sie einfach dies:

$build = $view_builder->view($entity);
$render_array = render($build);
$output['entity'] = $render_array;

mit:

$output = $view_builder->view($entity);

um ein Render-Array zurückzugeben und Twig das Rendering übernehmen zu lassen).

Wenn Sie jedoch weiter gehen, müssen (und sollten) Sie dafür nicht direkt in die Datenbank gehen. Der Entitätstyp-Manager funktioniert für alle Entitätstypen, einschließlich Ihrer eigenen, und Entitätsspeicherklassen verfügen über Methoden, die dabei helfen.

(Abgesehen davon sollte dieser Dienst auch injiziert und nicht von der statischen Drupal -Klassenmethode geladen werden. Ihre Controller-Klasse ist container-fähig.).

Sobald dies verfügbar ist, wird der Code folgendermaßen vereinfacht:

public function content($name) {
  $build = [];
  $entity_type = 'foo';

  $storage = $this->entityTypeManager->getStorage($entity_type);
  $entities = $storage->loadByProperties(['name' => $name]);

  if ($entity = reset($entities)) {
    $build = $this->entityTypeManager->getViewBuilder($entity_type)->view($entity);
  }

  return $build;
}

Um noch einen Schritt weiter zu gehen, können Sie Ihrer Entitätsklasse eine loadByName() -Methode mit einer geringfügigen Abweichung von den oben genannten Methoden hinzufügen. Dies kann Ihnen Zeit und Wiederholungen sparen.

4
Clive