Symfony 3, validateur personnalisé avec dépendance

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J'essaie d'implémenter une règle de validation personnalisée. La validation nécéssite un accès à la base de données, je définis donc mon validateur comme service dans le services.yml.

Quand je soumets le formulaire qui contient cette règle de validation, j'obtiens cette erreur:

1
Warning: Missing argument 1 for AppBundle\Validator\NotJunkEmailValidator::__construct(), called in C:\...\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory.php on line 71 and defined

Les classes de contrainte et de validateur sont visiblement bien trouvées, mais le système d'injection de dépendances de symfony ne semble pas transmettre doctrine au constructeur. Je ne comprends pas pourquoi. Qu'ais-je fait de faux ou que me manque-t-il ? A toutes fins utiles j'ai vidé le cache dev mais ça n'a rien changé.

JE pense pourtant avoir suivi au plus près ce qui est indiqué dans le cookbook ici: http://symfony.com/doc/current/validation/custom_constraint.html

Mon code est ci-dessous. Merci pour vos réponses.

La déclaration du service:

1
2
3
4
5
#app/config/services.yml
    validator.junkEmail:
        class: AppBundle\Validator\NotJunkEmailValidator
        arguments: ['@doctrine']
        tags: [{ name: validator.constraint_validator }]

La classe de contrainte:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
// src/AppBundle/Validator/NotJunkEmail.php
namespace AppBundle\Validator;
use Symfony\Component\Validator\Constraint;

/**
*@Annotation
*/
class NotJunkEmail extends Constraint {
public $message = "JunkEmailNotAllowed";
public $entity;
public $field;
}

Le validateur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
// src/AppBundle/Validator/NoJunkEmailValidator.php
namespace AppBundle\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class NotJunkEmailValidator extends ConstraintValidator {
private $doctrine;

public function __construct ($d) {
parent::__construct();
$this->doctrine=$d;
}

public function validate ($value, Constraint $constraint) {
//...
}

}

Extrait de l'entité utilisant ce validateur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
use AppBundle\Validator as Validator;

//...

/**
*@ORM\Column(type="string")
*@Assert\NotBlank
*@Assert\Email
*@Validator\NotJunkEmail(entity=JunkEmailDomain::class, field="domain")
*/
public $email;
+0 -0

Je ne sais pas trop si le service doctrine est public, peut-être que tu dois, pour tes propres services, utiliser doctrine.default ?

Je ne pense pas, je passe @doctrine comme paramètre à d'autres services et ça fonctionne.

Rajouts: Si je mets @doctrine.default , j'ai cette erreur:
The service "validator.junkemail" has a dependency on a non-existent service "doctrine.default".

A tout hasard j'ai essayé de mettre public: false, comme c'est le cas pour un autre service, mais ça ne change rien; je ne sais pas au juste ce que fait ce paramètre.

+0 -0

Problème résolu en ajoutant un alias dans service.yml et en modifiant la méthode validatedBy.

Il semblerait que cette façon de faire soit héritée de Symfony 2 et devrait être dépréciée en version 3. Toujours est-il que ce n'est expliqué nulle part dans la doc…

Dans NotJunkEmail.php:

1
2
<?php
public function validatedBy () { return 'antijunkmail'; }

Et dans services.yml:

1
2
3
4
    validator.junkEmail:
        class: AppBundle\Validator\NotJunkEmailValidator
        arguments: ['@doctrine']
        tags: [{ name: validator.constraint_validator, alias: antijunkmail }]
+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte