Entity API implementiert die Typed Data API
Erhebliche Verbesserung
- Entity API implementiert nun die API Typed Data
In dieser neuen Umsetzung der Entity API ist alles ein Feld, das auf derselben API basiert, wodurch Entities vorhersehbar und konsistent sind.
Verständnis des Drupal-Datenmodells
Zunächst, bevor wir in die Typed Data API eintauchen, müssen wir verstehen, wie das Drupal-Datenmodell (Entity API) bisher wahrgenommen wurde. Das ist wichtig, denn von hier aus stammt die Typed Data API, und Entity API ist eines der Systeme, für die sie entwickelt wurde.
Eine Entity ist ein komplexes Datenobjekt, das aus anderen Datenobjekten besteht, wie Feldern mit einer Liste von Elementen. Ein Feldelement ist ebenfalls komplex – es besteht aus weiteren Datenfragmenten, wie z.B. einem Textwert und einem Eingabeformat. Die Komplexität endet jedoch so, dass man etwas als primitiven Datentyp beschreiben kann, wie String oder Integer.
Vereinfachtes Beispiel aus Drupal 7 (ohne Sprachkennung, da Drupal 8 das anders handhabt):
Beispiel 1
// Entities sind komplex, sie enthalten andere Datenstücke.
$entity;
// Felder sind nicht komplex, sie enthalten nur eine Liste von Items.
$entity->image;
// Items sind komplex, sie enthalten weitere Datenstücke. Sie sind auch übersetzbar und zugriffsberechtigt.
$entity->image[0];
// Die Dateiid ist ein primitiver Integer.
$entity->image[0]['fid'];
// Der Alternativtext ist ein primitiver String.
$entity->image[0]['alt'];
Alles zusammengeführt
Nachfolgend ein vereinfachtes Beispiel, wie Entity API Interfaces implementiert, die sich von der Typed Data API unterscheiden. Tatsächlich erweitert die Entity API diese Interfaces, indem sie zusätzliche Methoden hinzufügt, die für Entity API notwendig sind. Trotzdem sind alle untenstehenden Aussagen wahr:
Beispiel 2
// Entities sind komplex.
$entity instanceof ComplexDataInterface;
// Properties sind nicht komplex, sie sind nur eine Liste von Items.
$entity->get('image') instanceof ListInterface;
// Items sind komplex.
$entity->get('image')->offsetGet(0) instanceof ComplexDataInterface;
// Das Typed Data Objekt, das den alt-Wert repräsentiert.
$entity->get('image')->offsetGet(0)->get('alt') instanceof TypedDataInterface;
// Der alt-Wert ist ein primitiver String.
is_string($entity->get('image')->offsetGet(0)->get('alt')->getValue());
Hier eine kurze Übersicht, wie Entity API die Typed Data API erweitert, um einige weitere Bedürfnisse zu erfüllen:
Beispiel 3
interface EntityInterface extends ComplexDataInterface, TranslatableInterface, AccessibleInterface {
// ...
}
interface FielditemListInterface extends ListInterface {
// ...
}
// Beachten Sie, dass dieses Interface zwei Interfaces erweitert. Erklärung folgt unten.
interface FieldItemInterface extends ComplexDataInterface, TypedDataInterface {
// ...
}
// Einige tatsächliche Implementierungen folgen.
// Erweitert eine abstrakte Klasse mit allgemeiner Logik.
class ImageItem extends FieldItemBase {
// ...
}
// Erweitert eine abstrakte Klasse mit allgemeiner Logik.
class String extends TypedData {
// ...
}
[Die folgenden zwei Absätze erfordern noch Überarbeitung]
Zwei auffälligste Punkte oben:
1. EntityInterface erweitert einige Service-Interfaces für Dinge wie Übersetzung und Zugriffsrechte. Das sollte ziemlich offensichtlich sein.
2. FieldItemInterface erweitert sowohl ComplexDataInterface als auch TypedDataInterface. Wie oben erklärt, sind Items komplex, weil sie weitere Datenfragmente enthalten (z.B. Textwert und Format für Textfelder). Gleichzeitig ist ein Item selbst ein Teil typisierter Daten und hat daher seine eigene Definition und Datentyp.
Zusammenfassend sind zusätzlich zu Beispiel 2 auch die folgenden Aussagen wahr:
Beispiel 4
$entity instanceof EntityInterface;
$entity->get('image') instanceof FieldItemListInterface;
$entity->get('image')->offsetGet(0) instanceof FieldItemInterface;
$entity->get('image')->offsetGet(0)->get('alt') instanceof String;
is_string($entity->get('image')->offsetGet(0)->get('alt')->getValue());
API-Nutzung
[In diesem Abschnitt werden noch weitere Beispiele benötigt]
Entity API definiert einige magische Methoden wie __get(), um schnellen und einfachen Zugriff auf Feldwerte zu ermöglichen. Dadurch ist die Nutzung der API sehr einfach, und die Syntax ähnelt der Zeit vor Drupal 8.
Das tatsächliche Auslesen des Alternativtextwertes eines Bildes sieht so aus:
Beispiel 5
// Die ausführlichste Variante.
$string = $entity->get('image')->offsetGet(0)->get('alt')->getValue();
// Mit von Entity API hinzugefügtem Magic.
$string = $entity->image[0]->alt;
// Noch mehr Magic von Entity API, das standardmäßig das erste Item aus der Liste holt.
$string = $entity->image->alt;
Das obige Beispiel fügt lediglich eine angenehmere Syntax zum alten API hinzu. Die folgenden Beispiele zeigen, wo der wirkliche Wert dieser API liegt – bei der Datenvalidierung:
Beispiel 6
// Gibt ein Array mit benannten Keys für alle Felder und deren
// Definitionen zurück, z. B. für das Feld ‘image’.
$property_definitions = $entity->getFieldDefinitions();
// Gibt ein Array mit benannten Keys für alle Properties und deren
// Definitionen zurück, z. B. für die Properties ‘file_id’ und ‘alt’.
$property_definitions = $entity->image
->getFieldDefinition()
->getFieldStorageDefinition()
->getPropertyDefinitions();
// Gibt nur die Definition für die Property ‘alt’ zurück.
$string_definition = $entity->image
->getFieldDefinition()
->getFieldStorageDefinition()
->getPropertyDefinition('alt');
Basierend auf den obigen Definitionen können wir nun intelligente Dinge tun, wie Serialisierung oder andere Datenarray-Operationen. Wir können diese Daten auch über semantisch reiche APIs bereitstellen, wie JSON-LD-Endpunkte, damit andere Systeme die Grundlagen unserer Daten verstehen.
Siehe https://drupal.org/node/2078241 für weitere Informationen zum Definieren und Nutzen von Field Definitions für Entity Types.