Valider vos données factices avec le bundle Symfony Alice
Publié le 15/10/2022 • Actualisé le 15/10/2022
Dans cet article, nous voyons comment valider des données factices avec le bundle Symfony Alice avant de les insérer en base de données. C'est l'essentiel afin de ne pas avoir de données invalides en environnements de développement ou de test. C'est parti ! 😎
Prérequis
Je présumerai que vous avez au moins les connaissances de base de Symfony et que vous savez charger des données factices avec le bundle hautelook/alice-bundle
.
Configuration
- PHP 8.3
- Symfony 6.4.12
- hautelook/alice-bundle 2.11
La référence composer hautelook/alice-bundle
, pointe en fait vers https://github.com/theofidry/AliceBundle, cliquez ici pour comprendre pourquoi.
Introduction
C'est quelque chose qui n'est a priori pas si évident. J'utilise le bundle Alice depuis longtemps, et c'est quelque chose dont je ne m'étais pas rendu compte. Je l'ai réalisé quand quelqu'un a posé une question à ce sujet sur le canal #alice-fixtures
du slack Symfony dev. J'ai vérifié, et en effet, la personne avait raison ; par défaut les fixtures ne sont pas validées. 😮
But
Le but ici va être de créer un simple processeur qui va vérifier que chaque fixture est valide avant de l'insérer en base. Nous allons, bien sûr, utiliser le validateur Symfony.
Le problème
Analysons le problème, voici les fixtures correspondant à cet article :
article_224 (extends article):
previous_article: '@article_216'
next_article: '@article_232'
name: 'Validating your data fixtures with the Alice Symfony bundle'
date_published: <date_create('2022-10-15')>
date_modified: <date_create('2022-10-15')>
keyword: 'symfony,fixtures,alice,validation,processor,data'
time_required: 3
stackoverflow_url: https://stackoverflow.com/q/28641360/633864
icon: fad fa-box-check
Ces fixtures étendent le modèle article
:
App\Entity\Article:
article (template):
#type: !php/const App\DBAL\Types\ArticleType::TYPE_BLOG_POST
type: !php/const App\Enum\ArticleType::BLOG_POST
active: true
author: <{pseudo}>
publisher: '@organization_strangebuzz'
in_language: <{locales_list}>
Maintenant, ajoutons une contrainte, par exemple, sur la propriété Author
de l'entité Article
. Ce n'est désormais plus un texte libre, mais il doit correspondre à certaines valeurs. Pour ce faire, nous pouvons utiliser la contrainte Symfony Choice
.
private const array ALLOWED_AUTHORS = ['COil', 'Soyuka', 'Dunglas'];
/**
* The author of this content or rating. Please note that author is special in that HTML 5 provides a special mechanism for indicating authorship via the rel tag. That is equivalent to this and may be used interchangeably.
*/
#[ORM\Column(type: 'text', nullable: false)]
#[Assert\NotBlank]
#[Assert\Choice(choices: self::ALLOWED_AUTHORS, message: '{{ value }} is an invalid value for the author! Allowed values are: {{ choices }}')]
#[Groups(groups: [Article::GROUP_DEFAULT])]
Dans ces fixtures, mettons une valeur autre que celles autorisées :
article_224 (extends article):
author: foobar
Si nous rechargeons les données, comme prévu, on n'a pas d'erreur. Dans la base de données, nous avons la valeur foobar
dans le champ auteur.
La solution ✨
Le bundle est extensible et permet d'effectuer des traitements avant et après insertion en base grâce aux processeurs ; ajoutons en un :
<?php
declare(strict_types=1);
namespace App\DataFixtures\Processor;
use App\Entity\Article;
use Fidry\AliceDataFixtures\ProcessorInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validator\ValidatorInterface;
final class ArticleProcessor implements ProcessorInterface
{
public function __construct(
private readonly ValidatorInterface $validator,
) {
}
public function preProcess(string $id, object $object): void
{
if (!$object instanceof Article) {
return;
}
/** @var ConstraintViolationList $violations */
$violations = $this->validator->validate($object);
if ($violations->count() > 0) {
$message = \sprintf("Error when validating fixture %s (Article), violation(s) detected:\n%s", $id, $violations);
throw new \DomainException($message);
}
}
public function postProcess(string $id, object $object): void
{
}
}
Grâce à Symfony, ce service est auto-configuré. Sinon, on doit lui assigner l'étiquette (tag) fidry_alice_data_fixtures.processor
.
Information for Service "App\DataFixtures\Processor\ArticleProcessor"
=====================================================================
---------------- ---------------------------------------------
Option Value
---------------- ---------------------------------------------
Service ID App\DataFixtures\Processor\ArticleProcessor
Class App\DataFixtures\Processor\ArticleProcessor
Tags fidry_alice_data_fixtures.processor
Public no
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
---------------- ---------------------------------------------
Quelques explications. On modifie la fonction preProcess()
car nous voulons valider les données avant l'insertion en base. Le premier argument string $id
est l'identifiant de la fixture, pour cet article, c'est article_224
. Le second argument est l'entité qui est en cours de traitement. Dans cet exemple, je ne déclenche la validation que si c'est une entité de type Article
mais on peut le faire pour toutes les entités. Dans ce cas, retirez le test instanceof
. Maintenant, essayons de recharger les données :
php bin/console doctrine:cache:clear-metadata
php bin/console doctrine:database:create --if-not-exists
php bin/console doctrine:schema:drop --force
php bin/console doctrine:schema:create
php bin/console doctrine:schema:validate
php bin/console hautelook:fixtures:load --no-interaction
In ArticleProcessor.php line 29:
Error when validating fixture article_224 (Article), violation(s) detected:
Object(App\Entity\Article).author:
"foobar" is an invalid value for the author! Allowed values are: "COil", "Soyuka", "Dunglas" (code 8e179f1b-97aa-4560-a02f-2a8b42e49df7)
hautelook:fixtures:load [-b|--bundle [BUNDLE]] [--no-bundles] [-m|--manager MANAGER] [--append] [--shard SHARD] [--purge-with-truncate]
make: *** [load-fixtures] Error 1
Victoire, on a désormais une erreur, et le chargement des données est interrompu (Rien n'est chargé). On a un message de débogage explicite avec l'identifiant de la fixture concernée et la liste des violations à corriger.
Conclusion
Nous avons vu comment valider des données factices Alice avec un processeur. Ça a été rapide à ajouter et dorénavant, nous sommes sûrs de ne plus insérer de données incorrectes dans la base de données. Ça a un léger coût en performances comme le validateur est appelé pour chaque fixture, mais c'est assez insignifiant au regard des tests additionnels ajoutés.
Et voilà ! J'espère que vous avez aimé. Découvrez d'autres informations en rapport à cet article avec les liens ci-dessous. Comme toujours, retours, likes et retweets sont les bienvenus. (voir la boîte ci-dessous) À bientôt ! COil. 😊
Lire la doc Plus sur Stackoverflow
Ils m'ont donné leurs retours et m'ont aidé à corriger des erreurs et typos dans cet article, un grand merci à : Laurent . 👍
A vous de jouer !
Ces articles vous ont été utiles ? Vous pouvez m'aider à votre tour de plusieurs manières : (cf le tweet à droite pour me contacter )
- Me remonter des erreurs ou typos.
- Me remonter des choses qui pourraient être améliorées.
- Aimez et retweetez !
- Suivez moi sur Twitter Suivez moi sur Twitter
- Inscrivez-vous au flux RSS.
- Cliquez sur les boutons Plus sur Stackoverflow pour me faire gagner des badges "annonceur" 🏅.
Merci d'avoir tenu jusque ici et à très bientôt sur Strangebuzz ! 😉
[🇫🇷] 5ème article de l'année : "Valider vos données factices avec le bundle Symfony Alice" https://t.co/xGgo94ZEIM Relectures, retours, likes et retweets sont les bienvenus ! 😉 Objectif annuel : 5 / 6 #symfony #alice #data #fixtures #php #validation
— COil #OnEstLaTech ✊ 🇺🇦 (@C0il) October 17, 2022