Comment valider une propriété dépendant d'une autre propriété, dans Symfony 2

Est-il possible de valider une propriété d'une classe de modèle dépend d'une autre propriété de la même classe?

Par exemple, j'ai cette classe:

class Conference
{
    /** $startDate datetime */
    protected $startDate;

    /** $endDate datetime */
    protected $endDate;
}

et je veux que Symfony 2.0 valide, que $startDate doit être après $endDate.

Est-ce possible par des annotations ou dois-je le faire manuellement?

28
demandé sur bostaf 2012-09-04 13:39:12

6 réponses

Oui, avec le rappel du programme de validation: http://symfony.com/doc/current/reference/constraints/Callback.html

Sur symfony 2.0:

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContext;

/**
 * @Assert\Callback(methods={"isDateValid"})
 */
class Conference
{

    // Properties, getter, setter ...

    public function isDateValid(ExecutionContext $context)
    {
        if ($this->startDate->getTimestamp() > $this->endDate->getTimestamp()) {
                $propertyPath = $context->getPropertyPath() . '.startDate';
                $context->setPropertyPath($propertyPath);
                $context->addViolation('The starting date must be anterior than the ending date !', array(), null);
        }
    }
}

Sur symfony master version:

    public function isDateValid(ExecutionContext $context)
    {
        if ($this->startDate->getTimestamp() > $this->endDate->getTimestamp()) {
            $context->addViolationAtSubPath('startDate', 'The starting date must be anterior than the ending date !', array(), null);
        }
    }

ici je choisis d'afficher le message d'erreur sur le champ startDate.

20
répondu Sybio 2012-09-04 09:50:49

à partir de Symfony 2.4 vous pouvez également utiliser Expression contrainte de validation pour obtenir ce dont vous avez besoin. Je crois que c'est la façon la plus simple de le faire. C'est plus pratique que de Rappel contrainte pour vous.

voici un exemple de mise à jour de votre classe model avec les annotations des contraintes de validation:

use Symfony\Component\Validator\Constraints as Assert;


class Conference
{
    /**
     * @var \DateTime
     *
     * @Assert\Expression(
     *     "this.startDate <= this.endDate",
     *     message="Start date should be less or equal to end date!"
     * )
     */
    protected $startDate;

    /**
     * @var \DateTime
     *
     * @Assert\Expression(
     *     "this.endDate >= this.startDate",
     *     message="End date should be greater or equal to start date!"
     * )
     */
    protected $endDate;
}

N'oubliez pas de activer les annotations dans votre projet configuration.

Vous pouvez toujours faire des validations encore plus complexes en utilisant syntaxe d'expression.

36
répondu Slava Fomin II 2014-10-24 19:02:37

D'une autre façon (au moins par Symfony 2.3) est d'utiliser simple @Assert\IsTrue:

class Conference
{
    //...

    /**
     * @Assert\IsTrue(message = "Startime should be lesser than EndTime")
     */
    public function isStartBeforeEnd()
    {
        return $this->getStartDate() <= $this->getEndDate;
    }

    //...
}

en tant Que référence, documentation.

10
répondu Damaged Organic 2016-04-28 11:01:36

c'est encore plus simple depuis la version 2.4. Tout ce que vous avez à faire est d'ajouter cette méthode à votre classe:

use Symfony\Component\Validator\Context\ExecutionContextInterface;

/**
 * @Assert\Callback
 */
public function isStartBeforeEnd(ExecutionContextInterface $context)
{
    if ($this->getStartDate() <= $this->getEndDate()) {
        $context->buildViolation('The start date must be prior to the end date.')
                ->atPath('startDate')
                ->addViolation();
    }
}

buildViolation méthode renvoie un constructeur qui a quelques autres méthodes pour vous aider à configurer la contrainte (comme les paramètres et la traduction).

9
répondu bostaf 2016-07-07 11:12:43

pour les validations de Date, nous pouvons tout simplement utiliser des contraintes de comparaison plus grandes que et plus grandes que L'Equal.

class Conference
{
     /**
     * @var \DateTime
     * @Assert\GreaterThanOrEqual("today")
     */
    protected $startDate;

     /**
     * @var \DateTime
     * @Assert\GreaterThan("startDate")
     */
    protected $endDate;
}

Pour plus d'informations, voir contraintes de validation

0
répondu Kisz Na 2018-07-31 07:09:03

une solution meilleure et plus propre https://symfony.com/doc/3.4/validation/custom_constraint.html est d'écrire

  • personnalisé contrainte (qui est en fait le message d'erreur)
  • et son validateur (qui est comme une fonction de contrôleur qui fait le contrôle

Pour vérifier que l'entité est fine, ajouter à la coutume contrainte (pas le validateur)

public function getTargets()
{
    return self::CLASS_CONSTRAINT;
}

Qui vous permet d'utiliser une instance de l'entité au lieu d'une simple valeur de propriété. Qu'il est possible d'écrire dans le programme de validation:

public function validate($object, Constraint $constraint)
{
    #Your logic, for example:
    if($value1 = $object->getValue1())
    {
        if($value2 = $object->getValue2())
        {
            if($value1 === $value2)
            {
                # validation passed
                return True;
            }
            else
            {
                # validation failed
                $this->context->buildViolation($constraint->message)
                    ->setParameter('{{ string }}', $value1.' !== '.$value2)
                    ->addViolation();
            }

La meilleure partie est que vous devez écrire dans la classe d'entité:

use YourBundle\Validator\Constraints as YourAssert;

/**
 * Yourentity
 *
 * @ORM\Table(name="yourentity")
 * @ORM\Entity(repositoryClass="YourBundle\Repository\YourentityRepository")
 *
 * @YourAssert\YourConstraintClassName # <-- as simple as this

Hope qui aide

0
répondu nicolallias 2018-09-27 07:00:54