Création de contenu personnalisé
Audience cible
Cette documentation s’adresse principalement aux développeurs ayant une expérience en programmation orientée objet en PHP, Drupal 6 ou Drupal 7, ainsi qu’à ceux qui souhaitent apprendre les principes de Drupal 8.
La documentation sur la création d’un type d’entité de contenu dans Drupal 8 inclut une liste complète des options disponibles.
Création d’un type de contenu sans bundle dans Drupal 8.
Dans ce cas, nous créons un objet contenu Drupal 8 qui n’a aucun bundle.
L’entité n’implémente pas l’API des champs, elle reste donc dans le code. Cela peut néanmoins servir de base pour construire des entités de contenu, car nous importerons plus tard des données plus complexes.
Enfin, lorsqu’il y aura des concepts OOP, je ferai référence à la documentation correspondante.
Contexte.
Notre module s’appelle advertiser.
Notre type d’entité de contenu s’appelle advertiser.
Notre nouveau contenu advertiser Drupal 8 aura les champs suivants :
- UUID
- ID
Définition de l’objet contenu dans Drupal 8.
Premièrement, tous les objets personnalisés résident désormais dans modules/custom au lieu de sites/all/modules/custom.
À l’intérieur de notre objet personnalisé, la structure des fichiers finale ressemble à ceci :
modules/custom/advertiser$ ├── advertiser.info.yml └── src └── Entity └── Advertiser.php
Pour référence, vous pouvez consulter l’entité Advertiser prête à l’emploi avec des ajouts supplémentaires comme des tests et des plugins de contraintes, mais pour l’instant tout sera plus simple.
Fichier info
Nous commençons par définir notre module personnalisé dans module_name.info.yml. Cela parle de lui-même :
name: Advertiser type: module description: 'Entité advertiser basique' package: custom core: 8.x
Squelette de l’entité
Entre-temps, la classe de base de l’entité Advertiser et le schéma associé sont définis dans src/Entity/Advertiser.php.
La première chose que nous faisons est de définir un namespace pour notre classe d’entité Advertiser. Cela sera utile lorsque nous voudrons utiliser nos classes.
namespace Drupal\advertiser\Entity;
Il est maintenant temps de définir notre entité via une annotation.
C’est la définition réelle du type d’objet que Drupal lit et met en cache, donc pensez à vider le cache après toute modification.
<?php /** * Définit l’entité advertiser. * * @ingroup advertiser * * @ContentEntityType( * id = "advertiser", * label = @Translation("Advertiser"), * base_table = "advertiser", * entity_keys = { * "id" = "id", * "uuid" = "uuid", * }, * ) */ ?>
Comme c’est une entité simple, nous utilisons seulement quelques propriétés, sans gestionnaires comme le module Access.
Nous avons un module fonctionnel qui définit notre entité de contenu personnalisée, mais on constate que la table « advertiser » n’a pas été créée dans la base de données.
$ drush sql-cli mysql> SHOW TABLES;
Cela vient du fait que notre classe ne contient pas de méthodes qui interagissent explicitement avec la base de données. De plus, il nous faut la définition minimale des méthodes nécessaires pour que l’entité interagisse correctement avec la base.
ContentEntityBase
On peut généralement ajouter des classes via quelque chose comme use Drupal\Core\Entity\ContentEntityBase; après la déclaration de namespace en haut du script. Cela rend ces méthodes disponibles pour notre propre classe qui peut les étendre ou, dans le cas d’interfaces, les implémenter.
Nous faisons deux choses : étendre la classe existante ContentEntityBase, qui a déjà les méthodes nécessaires pour interagir avec la base, et implémenter ContentEntityInterface pour décrire…
les méthodes dont nous avons besoin pour accéder à notre base de données. Cela NE décrit PAS comment nous le faisons. C’est le rôle de la classe IMPLEMENTANT. Nous pouvons implémenter cette interface autant de fois que nous voulons, de plusieurs façons différentes. Puis, nous pouvons changer d’implémentation sans affecter notre code, car l’interface définit comment nous allons l’utiliser, indépendamment de la façon dont elle fonctionne réellement. - https://secure.php.net/manual/en/language.oop5.interfaces.php
Tout cela signifie que nous obtenons ceci : N’oubliez pas d’ajouter toutes nouvelles classes avec un use en haut de votre script :
class Advertiser extends ContentEntityBase implements ContentEntityInterface {
Mais nous devons toujours utiliser ces nouvelles méthodes utiles pour insérer quelque chose dans la base. Nous commençons par définir les champs de base pour notre entité.
baseFieldDefinitions
La méthode baseFieldDefinitions provient de la classe ContentEntityBase que nous étendons.
Elle prend un paramètre :
La définition du type d’entité. Utile quand une même classe est utilisée pour plusieurs types d’objets, parfois dynamiques.
Et retourne :
Un tableau des définitions de champs de base pour le type d’entité, basé sur le nom du champ.
Nous l’implémentons ainsi :
<?php public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { // Champ standard, utilisé comme unique s’il est index primaire. $fields['id'] = BaseFieldDefinition::create('integer') ->setLabel(t('ID')) ->setDescription(t('L’ID de l’entité Advertiser.')) ->setReadOnly(TRUE); // Champ standard, unique en dehors du périmètre du projet actuel. $fields['uuid'] = BaseFieldDefinition::create('uuid') ->setLabel(t('UUID')) ->setDescription(t('L’UUID de l’entité Advertiser.')) ->setReadOnly(TRUE); return $fields; } ?>
À noter :
« Fournit les définitions des champs de base pour un type d’entité ».
- Méthode statique publique de FieldableEntityInterface.
« Classe pour définir les champs d’entité ».
- Toutes les méthodes dont nous avons besoin pour créer les champs, ajouter des contraintes, etc.
Entité complète
Au final, nous avons ceci :
<?php namespace Drupal\advertiser\Entity; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\ContentEntityInterface; /** * Définit l’entité advertiser. * * @ingroup advertiser * * @ContentEntityType( * id = "advertiser", * label = @Translation("advertiser"), * base_table = "advertiser", * entity_keys = { * "id" = "id", * "uuid" = "uuid", * }, * ) */ class Advertiser extends ContentEntityBase implements ContentEntityInterface { public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { // Champ standard, utilisé comme unique s’il est index primaire. $fields['id'] = BaseFieldDefinition::create('integer') ->setLabel(t('ID')) ->setDescription(t('L’ID de l’entité Advertiser.')) ->setReadOnly(TRUE); // Champ standard, unique en dehors du périmètre du projet actuel. $fields['uuid'] = BaseFieldDefinition::create('uuid') ->setLabel(t('UUID')) ->setDescription(t('L’UUID de l’entité Advertiser.')) ->setReadOnly(TRUE); return $fields; } } ?>
Après avoir installé votre module, vous devriez voir que la table « advertiser » a été ajoutée à la base de données !
$ drush sql-cli mysql> SHOW TABLES;
ou
drush sqlq "show tables like 'advertiser'" drush sqlq "describe advertiser"
Si votre module est déjà installé, vous devrez effectuer une mise à jour des entités.
Dans le ticket #2976035 : Les opérations CRUD avec des types d’entités doivent utiliser la dernière définition installée du type d’entité et du stockage des champs, la possibilité d’exécuter à distance à la demande a été supprimée, voir plus d’informations dans la note de changement correspondante.
Veuillez consulter le module Devel Entity Updates.