Rooneyl
Rooneyl

Reputation: 7902

Symfony2 Validator Constraint GreaterThan on other property

My validations are defined in a yaml file like so;

# src/My/Bundle/Resources/config/validation.yml
My\Bundle\Model\Foo:
    properties:
        id:
            - NotBlank: 
                groups: [add]
        min_time:
            - Range:
                min: 0
                max: 99
                minMessage: "Min time must be greater than {{ limit }}"
                maxMessage: "Min time must be less than {{ limit }}"
                groups: [add]
        max_time:
            - GreaterThan:
                value: min_time
                groups: [add]

How do I use the validator constraint GreaterThan to check against another property?
E.g make sure max_time is greater than min_time?

I know I can create a custom constraint validator, but surely you can do it using the GreaterThan constraint.
Hopefully I am missing something really simple here

Upvotes: 10

Views: 12739

Answers (3)

Alexander Sholk
Alexander Sholk

Reputation: 359

Try GreaterThan constraint with option propertyPath:

use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Column(type="datetime", nullable=true)
 * @Assert\DateTime()
 * @Assert\GreaterThan(propertyPath="minTime")
 */
 protected $maxTime;

Upvotes: 24

Shakus
Shakus

Reputation: 421

I suggest you use a Callback validator. Custom validators work too, but probably an overkill if this is a one off validation and won't be re-used in other parts of the application.

With Callback validators you can define them on the same Entity/Model and are called at Class level.

In your case

// in your My\Bundle\Model\Foo:
/**
 * @Assert\Callback
 */
public function checkMaxTimeGreaterThanMin($foo, Constraint $constraint)
{
        if ($foo->getMinTime() > $foo->getMaxTime()) {
            $this->context->addViolationAt('max_time', $constraint->message, array(), null);
        }
}

or if you're using YAML

My\Bundle\Model\Foo:
    constraints:
        - Callback: [checkMaxTimeGreaterThanMin]

Upvotes: 2

A.L
A.L

Reputation: 10513

I suggest you to look at Custom validator, especially Class Constraint Validator.

I won't copy paste the whole code, just the parts which you will have to change.

src/My/Bundle\Model\Foo/Validator/Constraints/CheckTime.php

Define the validator, min_time and max_time are the 2 fields you want to check.

<?php

namespace My\Bundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class CheckTime extends Constraint
{
    public $message = 'Max time must be greater than min time';

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

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

src/My/Bundle/Validator/Constraints/CheckTimeValidator.php

Define the validator:

<?php

namespace My\Bundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class CheckTimeValidator extends ConstraintValidator
{
    public function validate($foo, Constraint $constraint)
    {
            if ($foo->getMinTime() > $foo->getMaxTime()) {
                $this->context->addViolationAt('max_time', $constraint->message, array(), null);
            }
    }
}

src/My/Bundle/Resources/config/validation.yml

Use the validator:

My\Bundle\Entity\Foo:
    constraints:
        - My\Bundle\Validator\Constraints\CheckTime: ~

Upvotes: 3

Related Questions