Bonjour,
Je cherche à valider certaines propriétés de mes entités. Le système de validation de Symfony me semble être le plus pertinent mais j'ai néanmoins quelques contraintes et je me demande si ce système de validation est le "meilleur" à utiliser dans mon cas ou bien si je devrais créer mon propre service.
- Les validation ne doivent pas être bloquantes. Les utilisateurs complètent les entités au fur et à mesure qu'ils reçoivent les informations ce qui peut s'étaler sur plusieurs jours. Certaines validations ne devraient même être qu'indicatives, un conseil auprès de l'utilisateur lorsqu'il ne respecte pas les bonnes pratiques de l'entreprise mais dans certains cas, il est nécessaire de passer outre. Il faut qu'il soit clairement informé de ce qu'il fait.
- Les validations ne doivent pas être dans l'entité. Je souhaite que mes entités restent des fichiers exclusivement modifiées par la console de Symfony et je souhaite également que les validations soient isolées dans un fichier par entité afin de pouvoir toutes les survolées rapidement. Certaines validations concernent la cohérence entre plusieurs champs et ne sont donc pas appliquées à un champ spécifique mais à la classe toute entière. Tout isolé dans un seul fichier me parait une solution plus lisible.
- Lorsque les validations ne retournent plus aucune erreur, je souhaite que mon workflow qui suit puisse être lancé. Pour cela, dans un fichier guard de transition, il me faudrait quelque chose du genre if ($entity->NoValidationErrors()) then GO, existe-t-il ce genre de fonctions ? Je n'arrive pas à trouver
- En dernière contrainte, je souhaite être capable d'afficher l'ensemble des validations Warning et Error sur une page dédiée, en plus de l'affichage déjà existant par défaut sur chacun des formulaires. Je ne trouve pas de fonction qui me permette de faire cela.
Pour le moment :
- J'arrive à enregistrer mes entités même si il y a des erreurs de validations en ignorant le $form->isValid().
- J'arrive également à afficher les validations dès que j'arrive sur ma page en exécutant un $form->submit() dans mon controleur.
- J'ai isolé mes validations dans une classe spécifique qui est appelée par un callback depuis mon entité
Pour information, voici à quoi ressemble ma classe CompanyValidator pour le moment, cette classe a pour vocation de valider les parametres de l'entité Company :
L'entité est validée grâce au code ci-dessous :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 <?php namespace App\Entity\Validators; use App\Entity\Company; use Symfony\Component\Validator\Context\ExecutionContextInterface; /** * @Annotation */ class CompanyValidator extends BaseValidator // La classe BaseValidator ne contient que la méthode start_with pour le moment { public static function validate(Company $company, ExecutionContextInterface $context, $constraint) { // un dump($constraint) m'indique que la variable est null // Ici, on parcourt toutes les methodes qui commencent par "check_" $class_methods = get_class_methods('App\Entity\Validators\CompanyValidator'); foreach ($class_methods as $method_name) { if ((new parent)->startsWith($method_name, 'check_')) { call_user_func( array( (new self), $method_name ), $company, $context, $constraint ); } } } private function check_Name_(Company $company, ExecutionContextInterface $context, $constraint) { $message = 'Le nom est incorrect.'; if (!preg_match('/^\S{3,}\z/', $company->getName())) { $context->buildViolation($message) ->atPath('Name') ->addViolation(); } } private function check_Attribut2_(Company $company, ExecutionContextInterface $context, $constraint) { // Idem fonction check_Name_pour d'autres attributs } // Ma fonction ideale, mais qui ne fait pas ce que je veux private function check_AttributX_(Company $company, ExecutionContextInterface $context, $constraint) { $message = 'Le nom est incorrect.'; $severity = 'WARNING' if (!preg_match('/^\S{3,}\z/', $company->getAttributX())) { $context->buildViolation($message) ->atPath('AttributX') ->setSeverity($severity) // Si ça marchait, ce serait top, j'ai vu qu'il existait une notion de Payload mais je n'arrive pas à l'utiliser correctement car il me l'affecte au payload de la constraint du context (c'est a dire, le meme payload pour l'ensemble des violations du context) et non au payload de la constrainte de cette violation qui va etre ajoutee ->addViolation(); } } private function check_Attribut2_and_Attribu3_identiques(Company $company, ExecutionContextInterface $context, $constraint) { $message = 'Les attributs ne sont pas identiques.'; $severity = 'WARNING'; if ($company->getAttribut2() != $company->getAttribut3()) { $context->buildViolation($message) ->atPath('Attribut2') ->addViolation(); $context->buildViolation($message) ->atPath('Attribut3') ->addViolation(); } } }
Il me reste à trouver comment affecter une sévérité a une contrainte et comment "parcourir" les validations et donc trouver un moyen de récupérer l'ensemble des validations en erreur ou en warning dans un tableau par exemple pour pouvoir l'exploiter dans un controleur/service ou dans un template.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 <?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Entity(repositoryClass="App\Repository\CompanyRepository") * @Assert\Callback({"App\Entity\Validators\CompanyValidator", "validate"}) */ class Company { // ... }
Merci par avance,
Partager