API des entités Implémente l'API Typed Data
Amélioration significative
- Entity API implémente désormais l’API Typed Data
Dans cette nouvelle implémentation, Entity API considère tout comme un champ basé sur la même API, ce qui rend les entités prévisibles et cohérentes.
Comprendre le modèle de données de Drupal
Tout d’abord, avant de plonger dans l’API Typed Data elle-même, il faut comprendre comment le modèle de données Drupal (Entity API) était perçu auparavant. C’est important car c’est de là que vient l’API typed data, et Entity API est l’un des systèmes pour lesquels elle a été conçue.
Une entité est une partie complexe de données, composée d’autres morceaux de données, comme des champs contenant une liste d’éléments. Un élément de champ est aussi complexe — il est constitué de plus petits fragments de données, comme une valeur texte et un format d’entrée. Cependant, la complexité va seulement jusqu’à un certain point : certains éléments peuvent être décrits comme un type de données primitif, comme une chaîne ou un entier.
Exemple simplifié de Drupal 7 (exemple sans clé de langue, car Drupal 8 le gère différemment) :
Exemple 1
// Les entités sont complexes, elles contiennent d’autres morceaux de données. $entity; // Les champs ne sont pas complexes, ils contiennent seulement une liste d’items. $entity->image; // Les items sont complexes, ils contiennent d’autres morceaux de données. Ils sont aussi traduisibles et accessibles (permissions). $entity->image[0]; // L’ID de fichier est un entier primitif. $entity->image[0][‘fid’]; // Le texte alternatif est une chaîne primitive. $entity->image[0][‘alt’];
Regroupons tout
Voici un exemple simplifié de la manière dont Entity API implémente des interfaces autres que l’API Typed Data. En réalité, Entity API étend ces interfaces en ajoutant des méthodes supplémentaires nécessaires à Entity API. Néanmoins, toutes les affirmations suivantes sont vraies :
Exemple 2
// Les entités sont complexes. $entity instanceof ComplexDataInterface; // Les propriétés ne sont pas complexes, elles sont seulement une liste d’items. $entity->get('image') instanceof ListInterface; // Les items sont complexes. $entity->get('image')->offsetGet(0) instanceof ComplexDataInterface; // L’objet typed data représentant la valeur alt. $entity->get('image')->offsetGet(0)->get('alt') instanceof TypedDataInterface; // La valeur alt est une chaîne primitive. is_string($entity->get('image')->offsetGet(0)->get('alt')->getValue());
Voici un résumé de la manière dont Entity API étend l’API Typed Data pour satisfaire certains besoins additionnels :
Exemple 3
interface EntityInterface extends ComplexDataInterface, TranslatableInterface, AccessibleInterface { // ... } interface FielditemListInterface extends ListInterface { // ... } // Notez que cette interface étend deux interfaces. Explication ci-dessous. interface FieldItemInterface extends ComplexDataInterface, TypedDataInterface { // ... } // Voici quelques implémentations concrètes. // Étend une classe abstraite avec une logique commune. class ImageItem extends FieldItemBase { // ... } // Étend une classe abstraite avec une logique commune. class String extends TypedData { // ... }
[Les deux paragraphes suivants nécessitent un travail supplémentaire]
Les deux points les plus remarquables ci-dessus :
1. EntityInterface étend certaines interfaces utilitaires pour des fonctionnalités comme la traduction et l’accessibilité. Cela devrait être assez clair.
2. FieldItemInterface étend à la fois ComplexDataInterface et TypedDataInterface. Comme expliqué précédemment, les items sont complexes dans le sens où ils contiennent plusieurs fragments de données (par exemple une valeur texte et un format pour les éléments textuels). Mais en même temps, un item fait partie des données typées, ayant donc sa propre définition et type de données.
Pour résumer, en plus de l’exemple 2, toutes les affirmations ci-dessous sont aussi vraies :
Exemple 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());
Utilisation de l’API
[Cette section nécessite encore quelques exemples]
Entity API définit certaines méthodes magiques, comme __get(), pour permettre un accès rapide et simple aux valeurs des champs. Ainsi, l’utilisation de l’API est très simple, avec une syntaxe rappelant l’ère avant Drupal 8.
Voici comment extraire la valeur réelle du texte alternatif d’une image :
Exemple 5
// La manière la plus verbeuse. $string = $entity->get('image')->offsetGet(0)->get('alt')->getValue(); // Avec la magie ajoutée par Entity API. $string = $entity->image[0]->alt; // Avec encore plus de magie ajoutée par Entity API, pour récupérer par défaut le premier item // dans la liste. $string = $entity->image->alt;
L’exemple ci-dessus ne fait qu’ajouter une belle syntaxe à l’ancienne API. Les exemples suivants montrent où la véritable valeur de cette API se manifeste — la validation des données :
Exemple 6
// Retourne un tableau avec des clés nommées pour tous les champs et leurs définitions. // Par exemple le champ ‘image’. $property_definitions = $entity->getFieldDefinitions(); // Retourne un tableau avec des clés nommées pour toutes les propriétés et leurs définitions. // Par exemple les propriétés ‘file_id’ et ‘alt’. $property_definitions = $entity->image ->getFieldDefinition() ->getFieldStorageDefinition() ->getPropertyDefinitions(); // Retourne uniquement la définition pour la propriété ‘alt’. $string_definition = $entity->image ->getFieldDefinition() ->getFieldStorageDefinition() ->getPropertyDefinition('alt');
À partir de ces définitions, nous pouvons maintenant faire des choses intelligentes comme la sérialisation ou la conversion en d’autres tableaux de données. Nous pouvons également exposer ces données via des API riches sémantiquement, comme un endpoint JSON-LD, pour que d’autres systèmes comprennent la structure fondamentale de nos données.
Voir https://drupal.org/node/2078241 pour plus d’informations sur la manière de définir et d’utiliser les définitions des champs de type entité.