Le validateur UniqueEntity fourni dans la standard edition de Symfony2 permet de vérifier l’unicité d’un ou plusieurs champs d’une entité. Très simple à mettre en place, son utilisation se complique un peu dans le cas d’un champ commun partagé dans un héritage.
Cas simple : une seule classe “User”
Imaginons une classe User toute simple, dont la propriété username doit être unique :
Validation
Tentons d’assigner le même username à deux User différents : le validateur détecte la duplicité et remonte une erreur.
Cas complexe : 2 classes “Patient” et “Doctor” héritant de “User”
Imaginons maintenant que nous ayons 2 types d’utilisateurs : Doctor et Patient, qui étendent notre classe User d’origine où se trouve le champ username à valider.
Mettons en place un héritage doctrine (de type Class Table Inheritance) :
Idem pour l’entité Doctor.
Validation
Tentons d’assigner le même username à deux Doctor ou à deux Patient : le validateur détecte la duplicité et renvoie une erreur. Essayons maintenant de donner le même username à un Patient et à un Doctor : le validateur ne détecte pas d’erreur.
Problème
En interne, le validateur utilise la méthode findBy du repository de l’entité à valider. Dans le cas d’un héritage doctrine, cette méthode filtre les entités à valider en se basant sur leur discriminant, et ne prend donc pas en compte les autres entités filles.
Solution
Changeons ce fonctionnement en implémentant notre propre méthode, disons findByUsername.
À noter La méthode findByUsername doit être implémentée dans le repository de chaque classe fille et renvoyer des objets hydratés afin de pouvoir les comparer.
Pour cet exemple, nous allons créer un UserRepository dont les DoctorRepository et PatientRepository hériteront :
Idem pour le repository DoctorRepository.
Il ne reste plus qu’à spécifier au validateur la méthode du repository à utiliser. Dans notre cas c’est au niveau de l’annotation UniqueEntity déclarée dans la classe User parent :
Voilà, en espérant que ça vous aidera !