Einführung in die Entity API in Drupal 8
System von Entities in Drupal 8
Entities sind typisierte Klassen mit Methoden
Generische Methoden |
$entity->id() |
Entity-Typ-spezifische Methoden | $node->getTitle() |
Hintergrund
Das Entity-System wurde gegen Ende der Entwicklungsphase von Drupal 7 mit grundlegenden Standards zum Laden von Entities eingeführt. Das beigetragene entity.module erweiterte die API weiter, indem es Unterstützung für das Speichern und Löschen von Entities sowie viele weitere Verbesserungen hinzufügte.
Die meisten dieser Verbesserungen sind jetzt in Drupal 8 enthalten. Entity-Validierung wird jetzt in einer eigenen API durchgeführt (die z. B. Entities überprüfen kann, die über REST gespeichert wurden und nicht über ein Formular).
Zwei Varianten
Entity-Typen im Core gibt es in zwei Varianten.
Konfigurationsobjekt
Verwendet das Configuration System. Unterstützt Übersetzungen und kann Standardbenutzereinstellungen für Installationen bereitstellen. Konfigurationsobjekte werden in einer gemeinsamen Konfigurationstabelle der Datenbank als Strings gespeichert.
Content Entity
Besteht aus konfigurierbaren und Basisfeldern, kann Revisionen haben und Übersetzungen unterstützen. Content Entities werden in einer eigenen Datenbanktabelle als Strings gespeichert. Der Tabellenname entspricht dem Entity-"id"-Namen, und die Spalten werden durch die Methode „baseFieldDefinitions“ des Objekts definiert.
Bundles
Bundles sind unterschiedliche Varianten eines Entity-Typs. Zum Beispiel sind bei dem Entity-Typ Node die Bundles die verschiedenen Inhaltstypen wie „Article“ und „Page“.
Üblicherweise wird ein Bundle durch ein Konfigurationsobjekt dargestellt, obwohl es in Contrib-Modulen auch andere Modelle gibt. So ist im Beispiel Node der Node-Typ „article“ selbst ein Konfigurationsobjekt. Die Konfiguration speichert die Unterschiede zwischen Content-Entity-Typen, wie Einstellungen und Felder. Wenn Sie einen neuen Entity-Typ mit Bundles erstellen, erstellen Sie sowohl eine Content Entity, die den Inhalt und dessen Operationen verwaltet, als auch ein Konfigurationsobjekt, das die Unterschiede zwischen Content Entity-Typen regelt.
Annotations
Beim Erstellen eines neuen Entity-Typs müssen Sie das im Core integrierte Annotation-System verwenden. Annotationen sehen aus wie Docblock-Kommentare über der Klasse, werden aber vom Drupal-Kern analysiert und zwischengespeichert. In vielerlei Hinsicht ersetzen Annotationen einige der älteren Stile, die in Drupal 7 verwendet wurden.
Annotation Parser
Annotationen werden zur Laufzeit von einem Annotation-Mechanismus gelesen und analysiert. Drupal 8 verwendet den Doctrine Annotation Parser, der sie in ein Objekt umwandelt, das PHP nutzen kann.
Syntax. Die Annotation-Syntax ist in @ClassName() eingeschlossen, besteht hauptsächlich aus Key/Value-Paaren und kann Arrays mit geschweiften Klammern enthalten. Oberste Schlüssel brauchen keine Anführungszeichen, Array-Schlüssel jedoch schon. Jedes Key/Value-Paar steht in einer eigenen Zeile, die mit einem Komma endet. Bestimmte Funktionen können auf Werte angewandt werden, insbesondere die Funktion @Translation().
Beispiel für eine Annotation-Syntax:
/** * @ContentEntityType( * id = "my_entity_type_id", * label = @Translation("My entity type label"), * example_pair = "this_examples_value", * example_array = { * "array_key" = "array_value", * "some_other_key" = "some_other_value", * }, * ) */
Übliche oberste Annotation-Schlüssel
Key = "Beispielwert" | Beschreibung | Entity-Variante |
id = "node", | Maschinenname für den Entity-Typ. | Content & Config |
label = @Translation("Node"), | Lesbarer Name für den Entity-Typ. | Content & Config |
admin_permission = "administer nodes", | Berechtigung, die administrativen Zugriff erlaubt, um den Entity-Typ zu konfigurieren und zu verwalten. Erforderlich, wenn die Entity keinen eigenen Access-Handler definiert. | Content & Config |
bundle_label = @Translation("Content type"), | Optionaler lesbarer Name für den Bundle-Typ. | Content |
bundle_entity_type = "node_type", | Wenn Content Entities mit Bundles verwendet werden, muss dies die „ID“ des Konfigurationsobjekts sein. In diesem Fall ist „node_type“ ein Konfigurationsobjekt. | Content |
base_table = "node", | Datenbanktabellenname für den Entity-Typ. | Content |
fieldable = TRUE, | (Boolean) Gibt an, ob der Entity-Typ über die UI mit Feldern erweiterbar ist. | Content |
field_ui_base_route = "entity.node_type.edit_form", | Name der Route, an die die Feld-UI für das Entity gebunden ist. | Content |
Handler
Handler werden in der Entity-Annotation als Array definiert. Sie unterstützen die Entity, indem sie bestimmte Ausführungsbereiche auf andere PHP-Klassen auslagern. Diese Klassen „verarbeiten“ die zugewiesenen Bereiche der Entity-Ausführung.
Storage – verwaltet Laden, Speichern und Löschen der Entity. Standardmäßig verwenden Content Entities Drupal\Core\Entity\Sql\SqlContentEntityStorage, während Config Entities Drupal\Core\Config\Entity\ConfigEntityStorage verwenden. Sie können einen Storage-Handler definieren, um die Standard-Storage-Methoden Ihrer Entity zu erweitern. Beispielsweise, um zusätzliche Methoden bereitzustellen, die Revisions-IDs oder Übersetzungsanzahlen sammeln.
Beispiel: "storage" = "Drupal\node\NodeStorage",
Form – in den Handler-Annotationen jeder Entity gibt es mehrere Form-Handler, die die Formulare zum Hinzufügen, Bearbeiten und Löschen einer Entity auf andere PHP-Klassen abbilden.
Beispiel:
"form" = { "add" = "Drupal\block\BlockForm", "edit" = "Drupal\block\BlockForm", "delete" = "Drupal\block\Form\BlockDeleteForm", }
Außerdem können Sie eine „default“-Form definieren, die sowohl „add“ als auch „edit“ abdeckt, ohne sie einzeln anzugeben. Die „delete“-Form wird fast immer durch eine separate Klasse behandelt, da es sich meist um ein Bestätigungsformular handelt, das den Nutzer fragt, ob er wirklich löschen möchte.
View builder – stellt die Klasse bereit, die für die Ausgabe der Entity beim Betrachter verantwortlich ist. Zum Beispiel wird die Node-Ausgabe auf einer Drupal 8-Seite vom NodeViewBuilder verarbeitet.
Beispiel: "view_builder" = "Drupal\node\NodeViewBuilder",
List builder – die List Builder-Klasse ist für die Anzeige von Entity-Listen im Admin-Bereich verantwortlich. Sie bestimmt Kopfzeilen, Zeilen und Operationen auf der Entity-Übersichtsseite. Zum Beispiel zeigt die Seite /admin/content in Drupal die Liste der Nodes an, die vom NodeListBuilder geliefert wird.
Beispiel: "list_builder" = "Drupal\node\NodeListBuilder",
Route provider – ein optionaler Handler, der, wenn implementiert, Routen zur Verwaltung der Entity generiert. Diese Implementierung kann die in der routing.yml-Datei definierten Entity-Pfade ersetzen. Route_provider funktioniert zusammen mit Links, die für Ihre Entity definiert sind (siehe Abschnitt „Links“ unten). Die Annotation ist ein Array.
Beispiel:
"route_provider" = { "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", }
Access – ein Access-Handler kann verwendet werden, um dynamisch Zugriffsberechtigungen für Ihre Entity zu prüfen. Er verweist auf eine Klasse, die EntityAccessControlHandlerInterface implementiert. Der Core liefert eine Implementierung mit EntityAccessControlHandler, aber für mehr Kontrolle sollten Sie diese Klasse erweitern.
Beispiel: "access" = "NodeAccessControlHandler",
Views data – ermöglicht es, die Views-Daten mit Entitätsdaten zu erweitern. Damit können Sie z. B. baseFieldDefinitions als Views-Felder einbinden, Tabellen auf Entity-Beziehungen joinen oder andere Views-Daten ändern.
Beispiel: "views_data" = "Drupal\node\NodeViewsData",
Storage schema – kann implementiert werden, um die DB-Schema-Einstellungen weiter zu verändern, z. B. zusätzliche Tabellenindizes.
Beispiel: "storage_schema" = "Drupal\node\NodeStorageSchema",
Translation – kann verwendet werden, um zu verändern, wie die Entity-Formulare mit Übersetzungen interagieren.
Beispiel: "translation" = "Drupal\node\NodeTranslationHandler",
Beispiel für vollständige Handler:
Der Drupal-Core liefert viele Handler „out of the box“, doch oft möchten Sie eigene Klassen erweitern, um mehr Kontrolle und Anpassung zu erhalten. Hier ein vollständigeres Beispiel für Handler-Annotationen mit Standardklassen, die Sie erweitern können:
handlers = { "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", "list_builder" = "Drupal\Core\Entity\EntityListBuilder", "access" = "Drupal\Core\Entity\EntityAccessControlHandler", "views_data" = "Drupal\views\EntityViewsData", "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage", "storage_schema" = "Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema", "translation" = "Drupal\content_translation\ContentTranslationHandler", "form" = { "default" = "Drupal\Core\Entity\ContentEntityForm", "add" = "Drupal\Core\Entity\ContentEntityForm", "edit" = "Drupal\Core\Entity\ContentEntityForm", "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm", }, "route_provider" = { "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", }, },
Links
Links werden in der Entity-Annotation als Array definiert. Sie haben bestimmte Schlüssel, deren Werte URI sind, an denen der Entity-Typ oder einzelne Entities dieses Typs verwaltet werden können. Diese Entities können Content- oder Config-Entities sein.
Beispiel:
id = "node", handlers = { "route_provider" = { "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider" } }, links = { "canonical" = "/node/{node}", "add-page" = "/node/add", "add-form" = "/node/add/{node_type}", "edit-form" = "/node/{node}/edit", "delete-form" = "/node/{node}/delete", "collection" = "/admin/content", },
Beachten Sie, dass dies kein wörtliches Beispiel aus dem Node-Modul ist, sondern ein Beispiel.
Das Anlegen dieser Links erstellt nicht automatisch die Routen für diese URIs. Um diese Links nutzbar zu machen, muss Ihr Modul entweder eine eigene routing.yml-Datei bereitstellen oder den route_provider-Handler in der Entity-Annotation verwenden.
Links und Route Provider
Die oben genannten Links in Verbindung mit „route_provider“ machen folgende benannte Routen für Drupal verfügbar.
Link-Schlüssel | Routenname | Beispiel-URI | Beschreibung |
canonical | entity.node.canonical | /node/1 | Ansicht eines bestimmten Nodes |
add-page | entity.node.add_page | /node/add | Seite zur Auswahl des zu erstellenden Node-Typs |
add-form | entity.node.add_form | /node/add/article | Formular zum Hinzufügen eines Nodes eines bestimmten Bundles |
edit-form | entity.node.edit_form | /node/1/edit | Formular zum Bearbeiten eines bestimmten Nodes |
delete-form | entity.node.delete_form | /node/1/delete | Formular zum Löschen eines bestimmten Nodes |
collection | entity.node.collection | /admin/content | Ansicht aller Nodes in einer Liste |
Verwendung von Links
Diese Links sind über die toUrl()-Methode eines Entities zugänglich:
$view_url_object = $entity->toUrl(); // Standard ist 'canonical' $edit_url_string = $entity->toUrl('edit-form')->toString();
Links:
- Entity API – Generierte Dokumentation.
- Erstellen einer benutzerdefinierten Content Entity – Einfaches benutzerdefiniertes Entity-Beispiel.
- Erstellen eines Content Entity-Typs in Drupal 8 – Erweiterte Beispiele mit Handlern, Berechtigungen, Routing und Links.
- Erstellen eines Config Entity-Typs in Drupal 8 – Erweiterte Beispiele mit Handlern, Routing und Schema.
- [Extern] Entity Type Walkthrough – Dokumentation für generische Entity-Typen in der Praxis
Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.