12.3 C
Madrid
viernes, diciembre 1, 2023
spot_img

Validation d’entité Drupal 8 et données typées expliquées – SitePoint

La validation des données est une partie très importante de toute application. Drupal 7 dispose d’une excellente API de formulaire qui peut gérer la validation complexe des données soumises, qui peuvent ensuite être transformées en entités. Cependant, la validation au niveau du formulaire est problématique. Par exemple, il devient difficile de gérer la validation des entités (données) par programmation. Nous devons soit réimplémenter la logique de validation, soit imiter les soumissions de formulaires dans le code. Cela rend toute interaction de données dépendante du système de formulaire et c’est une mauvaise idée.

Avec l’introduction de sous-systèmes tels que l’API REST, Drupal 8 avait besoin de quelque chose de mieux pour gérer ce problème. Le composant Symfony Validation a été choisi et Drupal 8 s’appuie dessus pour s’adapter aux réalités du système Entity basé sur les données typées et les plugins. Alors maintenant, les soumissions de formulaire valident les entités comme le font les appels REST ou toute autre interaction programmatique avec les entités peut facilement le faire.

Dans cet article et sa suite, nous allons explorer l’API de validation d’entité Drupal 8, voir comment cela fonctionne et comment il peut être étendu. Pour mieux comprendre cela, nous examinerons également l’API de données typées qui sous-tend le système d’entités dans Drupal 8. Il y aura des exemples de code qui existent déjà dans le noyau, mais nous écrirons également un peu de notre propre code qui peut être trouvé dans ce référentiel git dans le module de démonstration.

Données typées

Les données typées sont l’API Drupal 8 qui a été conçue pour fournir un moyen cohérent d’interagir avec les données ou les métadonnées sur les données elles-mêmes. Pourquoi est-ce important pour notre sujet ? Parce que la validation est définie et appelée sur des objets de données typés.

Deux composants importants de cette API se démarquent : la définition des données et les plugins DataType. Le rôle du premier est de définir les données et la façon dont l’interaction fonctionne avec elles (y compris des éléments tels que les paramètres ou les contraintes de validation). Le rôle de ce dernier est de fournir un moyen d’obtenir et de définir des valeurs à partir de ce type de données. Lorsqu’ils sont instanciés, les plugins de type de données utilisent des instances de définition de données transmises par le gestionnaire de plugins. Ce dernier peut également déduire quelle définition de données doit être utilisée par un type de plug-in DataType.

Voyons un exemple :

$définition = Définition des données::créer(‘chaîne de caractères’)
->addConstraint(‘Longueur’, déployer(‘max’ => 20));

Nous avons créé une définition de données de chaîne et lui avons appliqué la contrainte de longueur. Les contraintes sont un élément clé de l’API de validation et elles définissent le type de validation qui s’exécutera sur les données. Ils sont couplés à un validateur qui exécute réellement la tâche, mais nous en verrons plus sur les contraintes et les validateurs dans la deuxième partie de cette série.

Ensuite, nous utilisons le gestionnaire de plug-in DataType pour créer l’instance réelle du plug-in de type de données :

$string_typed_data = Drupal::typedDataManager()->créer($définition, ‘ma ficelle’);

Nous avons chargé le service de gestionnaire de manière statique ici par souci de concision, mais vous devez utiliser l’injection de dépendances dans votre projet si vous êtes dans un contexte de classe. La méthode create () sur le TypedDataManager prend la définition de données comme premier paramètre, la valeur réelle comme deuxième et renvoie une instance de plug-in DataType du type qui correspond à la définition : dans notre cas, StringData. Pour les données complexes, les plug-ins DataType peuvent spécifier dans leurs annotations la classe de définition de données qu’ils doivent utiliser. Et pour plus d’informations sur les plugins dans Drupal 8, assurez-vous de consulter mes articles précédents sur le sujet.

L’une des méthodes de cette instance de plugin est validate(), qui déclenche la validation des données par rapport à toutes les contraintes qui ont été appliquées à la définition et renvoie une instance de ConstraintViolationList de Symfony. En itérant dessus ou en utilisant des méthodes comme count() ou get(), nous pouvons vérifier si les données sont valides et quelles contraintes ont échoué si ce n’est pas le cas.

Dans notre exemple, la liste des violations ne doit pas contenir d’erreurs de validation car la chaîne que nous avons utilisée comporte moins de 20 caractères. Si nous avions utilisé une chaîne plus longue lors de la création du plugin, nous aurions eu une violation représentée par une instance Symfony ConstraintViolationInterface avec un message, une valeur incriminée et même un chemin de propriété.

Données typées et entités de contenu

Maintenant que nous en savons un peu plus sur l’API de données typées, voyons comment cela s’applique aux entités de contenu.

Les données d’entité dans Drupal 7 sont réparties entre les propriétés d’entité (généralement les colonnes de la table d’entité) et les champs de l’API de champ qui sont configurés via l’interface utilisateur. Dans Drupal 8, ils ont été regroupés sous le même parapluie afin que les anciennes propriétés deviennent également des champs. Cependant, une différence subsiste dans le fait que certains champs (principalement les anciennes propriétés d’entité) sont définis comme champs de base tandis que les autres sont des champs configurables.

Les définitions de données pour ces champs sont BaseFieldDefinition et FieldConfig, mais ce sont tous deux des implémenteurs de la même FieldDefinitionInterface (qui est une extension complexe de DataDefinitionInterface – l’interface directement implémentée par DataDefinition que nous avons vue précédemment).

Chaque champ individuel contient des données dans une implémentation spéciale de FieldItemListInterface et est toujours une liste de plugins FieldItem individuels (même s’il n’y a qu’une seule valeur réelle dans le champ). Chacun de ces plugins étend un plugin DataType et utilise un type d’implémentation DataDefinitionInterface lui-même (généralement FieldItemDataDefinition). Les choses sont assez complexes à ce niveau, il vaut donc la peine d’examiner de plus près la composition des champs d’entité pour mieux comprendre cette architecture.

Ajout de contraintes d’entité et de champ

Les contraintes de Drupal 8 sont également des plugins qui contiennent généralement une petite quantité d’informations sur la façon dont les données sont réellement validées, quel message d’erreur doit être utilisé en cas d’échec et toutes les options supplémentaires dont le validateur a besoin. La classe validator (qui est référencée par la contrainte) est responsable de la vérification des données. Nous avons vu un exemple, Length, qui est en fait la classe LengthConstraint validée directement par la classe LengthValidator de Symfony. Nous verrons dans la deuxième partie comment créer notre propre contrainte et validateur. Pour l’instant, cependant, voyons comment nous pouvons ajouter des contraintes existantes aux entités de contenu et aux champs.

Contraintes au niveau de l’entité

Les contraintes au niveau de l’entité sont ajoutées dans l’annotation de la classe d’entité elle-même. Par exemple, voici comment l’entité Commentaire a défini une contrainte pour sa combinaison de champs nom/auteur :


contraintes = {
«Nom du commentaire» = {}
}

Dans cet exemple, CommentName est l’ID de plug-in de la contrainte qui sera validée lors de l’enregistrement d’une entité de commentaire. Les accolades ouvrantes et fermantes signifient que le plugin ne prend aucune option.

Si nous voulions ajouter ou supprimer une contrainte d’une entité existante, nous devions implémenter hook_entity_type_alter() :

fonction demo_entity_type_alter(déployer &$entity_types) {

$nœud = $entity_types[‘node’];
$nœud->addConstraint(‘ConstraintPluginName’, [‘array’, ‘of’, ‘options’]);
}

Dans cet exemple, nous ajoutons une contrainte fictive à l’entité Node et lui transmettons un tableau d’options.

Contraintes au niveau du champ

Il existe plusieurs façons d’ajouter des contraintes au niveau du champ selon que le type d’entité de contenu est défini dans notre module et que le type de champ dont nous parlons est un champ de base ou configurable.

Si nous définissons notre propre type d’entité, l’une des méthodes sur la classe d’entité réelle que nous devons implémenter est baseFieldDefinitions(). C’est là que nous renvoyons un tableau de définitions de champs BaseFieldDefinition et nous pouvons facilement y ajouter nos contraintes. Par exemple, voici comment le champ de base Node ID est défini :

$champs[‘nid’] = Définition du champ de base::créer(‘entier’)
->setLabel(t(‘ID de nœud’))
->setDescription(t(‘L’identifiant du nœud.’))
->setReadOnly(vrai)
->setSetting(‘non signé’, vrai);

De la même manière que nous avons ajouté des contraintes à l’instance DataDefinition précédemment, l’entité Node pourrait également ajouter des contraintes au champ Node ID, plus précisément :

  • à la BaseFieldDefiniton elle-même, qui est, comme nous l’avons vu, la définition de l’implémentation FieldItemListInterface (la liste)
  • aux éléments FieldItemDataDefinition individuels, qui sont, comme nous l’avons vu, un type de définition de données complexes pour les implémentations FieldItemInterface (les éléments)

Si nous voulons ajouter une contrainte à un champ de base Node (ou à tout autre type d’entité de contenu non défini par notre module), nous devons implémenter hook_entity_base_field_info_alter() et y ajouter notre contrainte :

fonction demo_entity_base_field_info_alter(&$champs, DrupalCœurEntitéInterface de type d’entité $entity_type) {
si ($entity_type->identifiant() === ‘nœud’) {

$titre = $champs[‘title’];
$titre->addPropertyConstraints(‘évaluer’, [‘Length’ => [‘max’ => 5]]);
}
}

Dans l’exemple ci-dessus, nous ajoutons une contrainte au champ Titre du nœud pour nous assurer qu’aucun titre ne peut dépasser 5 caractères. Remarquez que nous utilisons la méthode addPropertyConstraint() au lieu de celle addConstraint() que nous avons vue précédemment. En effet, nous ne ciblons pas la définition de la liste d’éléments, mais les définitions d’éléments individuelles elles-mêmes (FieldItemDataDefinition).

En utilisant la méthode addConstraint(), nous ajoutons une contrainte à la liste complète des éléments. Cela signifie que lorsque la contrainte est validée, le validateur reçoit la liste entière et pas seulement la valeur de l’élément individuel.

Si nous voulons ajouter une contrainte à un champ configurable, le processus est assez similaire. La différence est que nous devons implémenter hook_entity_bundle_field_info_alter() et travailler avec des instances FieldConfig au lieu de BaseFieldDefinition.

Si nous voulons inspecter les contraintes déjà définies sur le terrain, nous pouvons faire quelque chose comme ceci :

$titre = $champs[‘title’];
$contraintes = $titre->getConstraints();
$property_constraints = $titre->getItemDefinition()->getConstraints();

Dans cet exemple, $title est soit une instance de BaseFieldDefinition soit FieldConfig. Le tableau $constraints est, comme prévu, une liste de contraintes appliquées à la liste complète des éléments de champ tandis que $property_constraints est un tableau de contraintes appliquées aux éléments de champ individuels eux-mêmes. Nous pouvons remarquer, cependant, que si nous exécutons ce code après avoir appliqué la contrainte de longueur, nous trouverons à l’intérieur de $property_constraints une contrainte ComplexData qui enveloppe les contraintes individuelles appliquées aux valeurs de champ. En effet, il peut y avoir plusieurs définitions de données individuelles pour un seul élément de champ et Drupal les regroupe par défaut de cette manière.

Conclusion

Dans cet article, nous avons commencé à examiner l’API de validation d’entité dans Drupal 8. À cette fin, nous avons également dû avoir une idée de l’API de données typées qui est utilisée comme base pour le système d’entités. Une fois que cela est devenu un peu plus clair, nous avons vu comment des contraintes peuvent être ajoutées à divers types de définitions de données, y compris celles utilisées par les entités et les champs.

Dans la partie suivante, nous verrons comment fonctionne la validation réelle et comment gérer les violations qui peuvent survenir. De plus, nous allons créer notre propre contrainte et validateur et appliquer nos connaissances de cette partie à divers types de définition de données. Amusement!

Artículos relacionados

Dejar respuesta

Please enter your comment!
Please enter your name here

- Anuncio -spot_img

Últimos artículos

3,913SeguidoresSeguir
0suscriptoresSuscribirte