3 votes

Symfony2/Doctrine - contrainte de validation qui nécessite l'accès à une base de données

J'ai une entité ArticlePattern qui possède une propriété pattern (chaîne de caractères). J'ai besoin d'accéder à la base de données pour vérifier si le motif est correct. J'aimerais donc définir une méthode ArticlePattern::isPatternValid() et ajouter une contrainte (en utilisant l'annotation de Doctrine) qui vérifierait si isPatternValid est vrai lors de la validation par l'objet Validator.

D'après ce que j'ai lu ici et là, ce n'est pas une bonne idée de faire dépendre une entité d'un conteneur de service, ce qui signifie que je ne peux pas accéder au service de doctrine depuis ArticlePattern::isPatternValid().

Comment puis-je créer une contrainte de validation personnalisée qui nécessite un accès à la base de données ? Comment gérez-vous de telles situations qui, je pense, sont très courantes, vu le nombre de questions sur l'accès à un conteneur de service à partir d'une classe d'entité.

EDITAR:

Ok, merci les gars, donc la réponse est a Contrainte de validation personnalisée

5voto

Crozin Points 22346

Un objet validateur peut être :

  • Un objet simple, qui n'a aucun lien avec l'environnement du cadre de travail.
  • Un service (dans le contexte de conteneur d'injection de dépendances ) qui peut faire absolument n'importe quoi du moment qu'il met en œuvre Symfony\Component\Validator\ConstraintValidatorInterface

Que devez-vous faire ?

  1. Définir une contrainte simple
  2. Annulation validatedBy() pour renvoyer le "nom" du validateur ( return 'my_validator'; )
  3. Définir un service simple dans DIC :

    <service id="project.validator.my" class="Project\Constraints\MyValidator">
        <!-- service definition here -->
    
        <!-- the service has to be tagged -->
        <tag name="validator.constraint_validator" alias="my_validator" />
    </service>

EDIT

Vous avez posé une question sur la validation de propriétés multiples. Dans ce cas, vous pouvez créer un validateur lié à l'objet plutôt qu'à la propriété de l'objet.

  1. Dans votre classe de contrainte, définissez la cible de cette contrainte (propriété / classe) :

    class MyConstraint ... {
        ...
    
        public function targets() {
            return self::CLASS_CONSTRAINT;
        }
    }
  2. Annoter une classe validée au lieu d'une propriété :

    @Assert/MyConstraint(...)
    class MyClass {
        private $firstName;
        private $lastName;
    
        @Assert/Email
        private $email;
    
        ...
    }
  3. Le validateur lui-même est à peu près le même que dans le cas de la validation d'une propriété :

    class MyValidator extends ConstraintValidator {
        public function isValid($value, Constraint $constraint) {
            // $value is an object rather a property
        }
    }

1voto

Kris Wallsmith Points 4804

Votre contrainte doit remplacer la contrainte de base validatedBy() et renvoie l'identifiant du service de validation des contraintes dans votre conteneur.

public function validatedBy()
{
    return 'my_pattern_validator';
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X