Types d’entités
- Drupal 7 - les entités étaient des objets génériques stdClass.
- Drupal 8 - les entités sont désormais des objets typés spécifiques, chaque type d'entité définissant la classe utilisée pour les instances de cette entité.
Exigences
Les classes d'entités doivent être placées dans l'espace de noms Entity du module qui fournit le type d'entité, par exemple \Drupal\[nom_module]\Entity. Cela signifie que les fichiers PHP de classe d'entité se trouvent dans le dossier src/Entity du module.
Le docblock de la classe doit contenir une annotation EntityType qui définit les métadonnées de ce type d'entité, incluant le label, les contrôleurs, les tables, etc. Pour une liste complète des propriétés, voir la classe \Drupal\Core\Entity\Annotation\EntityType.
Nomination
Les noms des types d'entité doivent être préfixés par le nom du module, sauf si le type d'entité et le nom du module sont identiques. Le préfixe dans le nom de la classe n'est pas nécessaire car il est dans l'espace de noms du module, qui est lui-même suffisamment significatif. Par exemple, le type d'entité pour les termes de taxonomie s’appelle taxonomy_term, et la classe correspondante est Drupal\taxonomy\Entity\Term.
Interfaces
Drupal 8 recommande d'utiliser des interfaces pour la typage et la documentation des méthodes plutôt que des classes concrètes. Par exemple, le stockage commun des entités reçoit le typage EntityInterface (ex: hook_entity_insert(EntityInterface $entity)), tandis que le stockage spécifique aux nœuds reçoit NodeInterface (ex: hook_node_insert(NodeInterface $node)).
Les champs/propriétés des entités sont souvent courts, orientés stockage et peu explicites. De plus, les entités de contenu n’utilisent pas forcément des propriétés spécifiques pour leurs champs (y compris les champs de base comme le titre).
La bonne pratique est donc de fournir une interface avec des méthodes bien nommées, en respectant les règles :
- Les méthodes ont des préfixes comme get/set/is : getSomething(), setSomething($value), isSomething().
- Ajouter uniquement des méthodes pour les choses que d’autres codes doivent modifier. Par exemple, la date de dernière modification d’un nœud ($node->updated) ne devrait pas être modifiable, donc on a getChangedTime() mais pas setChangedTime().
- Utiliser des noms explicites : la méthode pour accéder au statut d’un nœud est isPublished().
Compréhension
Pour savoir quels types d’entités un module fournit, consultez les classes dans l’espace de noms Entity du module, qui ont une annotation @EntityType contenant aussi un id (nom du type).
Pour localiser la définition d’un type d’entité donné, cherchez le préfixe du type. Si le module ne suit pas la convention, cherchez l’id = « $type ». Si vous connaissez la classe ou interface, l’espace de noms indique son origine.
Exemple
core/modules/node/src/Entity/Node.php: namespace Drupal\node\Entity; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Session\AccountInterface; use Drupal\node\NodeInterface; use Drupal\user\UserInterface; /** * Définit la classe d'entité node. * * @ContentEntityType( * id = "node", * label = @Translation("Content"), * bundle_label = @Translation("Content type"), * handlers = { * "storage" = "Drupal\node\NodeStorage", * "storage_schema" = "Drupal\node\NodeStorageSchema", * "view_builder" = "Drupal\node\NodeViewBuilder", * "access" = "Drupal\node\NodeAccessControlHandler", * "views_data" = "Drupal\node\NodeViewsData", * "form" = { * "default" = "Drupal\node\NodeForm", * "delete" = "Drupal\node\Form\NodeDeleteForm", * "edit" = "Drupal\node\NodeForm" * }, * "route_provider" = { * "html" = "Drupal\node\Entity\NodeRouteProvider", * }, * "list_builder" = "Drupal\node\NodeListBuilder", * "translation" = "Drupal\node\NodeTranslationHandler" * }, * base_table = "node", * data_table = "node_field_data", * revision_table = "node_revision", * revision_data_table = "node_field_revision", * translatable = TRUE, * list_cache_contexts = { "user.node_grants:view" }, * entity_keys = { * "id" = "nid", * "revision" = "vid", * "bundle" = "type", * "label" = "title", * "langcode" = "langcode", * "uuid" = "uuid", * "status" = "status", * "uid" = "uid", * }, * bundle_entity_type = "node_type", * field_ui_base_route = "entity.node_type.edit_form", * common_reference_target = TRUE, * permission_granularity = "bundle", * links = { * "canonical" = "/node/{node}", * "delete-form" = "/node/{node}/delete", * "edit-form" = "/node/{node}/edit", * "version-history" = "/node/{node}/revisions", * "revision" = "/node/{node}/revisions/{node_revision}/view", * } * ) */ class Node extends ContentEntityBase implements NodeInterface { // ... }
Pour avoir une vue complète des entités dans Drupal 8, vous pouvez consulter ce diagramme représentant les classes d’entités. Pour voir en grand, ouvrez dans un nouvel onglet :