Contraintes/validateurs, champ formulaire – PHP5 – Symfony 2

symfony_logo

Dans cet article, je vais vous expliquer comment rajouter des contraintes sur un champ d'une entité ; ici sur l'entité User de FOSUserBundle.

Utilisation d'une contrainte déjà existante sur un champ

Contraintes existantes (voir dossier "Symfony\Component\Validator\Constraints\") : Regexp, NotBlank, GreaterThan, Length, Count, ...

  • Possibilité de mettre la contrainte directement dans l'Entité sur le champ :
/**
* @Assert\NotBlank(message = "form.error.name_required")
*/
private $name;
  • ou dans le fichier "validation.yml"
MyName\UserBundle\Entity\User:
   properties:
       name:
          - NotBlank: { message: form.error.name_required }

Pour appliquer cette nouvelle contrainte sur un champ d'une entité, il faut donc tout simplement appliquer l'une de ces solutions.

Le message d'erreur paramétrée par cette contrainte s'affichera dans le formulaire au niveau du champ qui n'est pas valide.

Création de sa propre contrainte

Il est possible aussi de créer sa propre contrainte, son propre validateur.

Pour cela, il faut créer le nouveau Validator dans le dossier "Validator\Constraints" de notre Bundle.

Ex : Création du validateur NotInPreviousPasswords qui va interdire la réutilisation d'anciens mots de passes. Création de la classe NotInPreviousPasswordsValidator.php qui doit hériter de la classe ConstraintValidator.

La fonction validate de notre validateur (fonction fille de la classe ConstraintValidator) est la fonction dans laquelle on définit notre contrainte.

class NotInPreviousPasswordsValidator extends ConstraintValidator
{
      public function __construct([...])
      {
       [...]
      }

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

 

Compléter le fichier "validation.yml" de la manière suivante :

MyName\UserBundle\Entity\User:
   properties:
       plainPassword:
          - MyName\UserBundle\Validator\Constraints\NotInPreviousPasswords: { message: user.plainpassword.already used }

 

Dans le fichier "services.xml" on peut injecter les services dont on va avoir besoin (ex: EntityManager, SecurityContext, ...).

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
		[...]
        <parameter key="myname_user_change_password.validator.notinpreviouspassword.class">MyName\UserBundle\Validator\Constraints\NotInPreviousPasswordsValidator</parameter>
		<parameter key="myname_user_change_password.validator.nbLastDifferentPassword">2</parameter>
		[...]
    </parameters>

    <services>
		[...]
        <service id="myname_user.validator.notinpreviouspasswords" class="%myname_user_change_password.validator.notinpreviouspassword.class%">
            <argument type="service" id="logger" />
            <argument type="service" id="doctrine.orm.entity_manager"/>
            <argument type="service" id="security.context" />
            <argument type="service" id="security.encoder_factory" />
            <argument type="service" id="request_stack"/>
            <argument type="service" id="fos_user.user_manager"/>
            <argument>%myname_user_change_password.validator.nbLastDifferentPassword%</argument>
            <tag name="validator.constraint_validator" alias="myname_user.validator.notinpreviouspasswords" />
        </service>
		[...]
    </services>

</container>

 

Dans le service, le tag doit avoir pour valeur d'alias, la valeur retournée par la fonction "validatedBy()" de la classe NotInPreviousPassword.php.

Cette classe hérite de la classe Constraint et permet donc avec sa fonction "validatedBy()" de faire le lien entre la contrainte et son validateur.

<?php

namespace MyName\UserBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class NotInPreviousPasswords extends Constraint
{
    public $message;

    public function validatedBy()
    {
        return 'myname_user.validator.notinpreviouspasswords';
    }
}

Le message d'erreur, qui s'affichera si la contrainte n'est pas respectée, doit être déclarée ici. Elle peut être défini ici ou dans le fichier "validation.yml" comme vu plus haut.

 

Enregistrer

Enregistrer

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.