Подтвердить что ты не робот

Как проверить свойство, зависящее от другого свойства в Symfony 2

Можно ли проверить свойство класса модели, зависящее от другого свойства того же класса?

Например, у меня есть этот класс:

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

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

и я хочу, чтобы Symfony 2.0 подтверждал, что $startDate должен быть после $endDate.

Это возможно по аннотации или мне нужно сделать это вручную?

4b9b3361

Ответ 1

Да с валидатором обратного вызова: http://symfony.com/doc/current/reference/constraints/Callback.html

В 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);
        }
    }
}

В главном варианте Symfony:

    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);
        }
    }

Здесь я хочу показать сообщение об ошибке в поле startDate.

Ответ 2

Начиная с Symfony 2.4 вы также можете использовать Expression ограничение валидации для достижения того, что вам нужно. Я верю, что это самый простой способ сделать это. Это более удобно, чем ограничение Callback.

Здесь пример того, как вы можете обновить класс модели с аннотациями ограничений проверки:

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;
}

Не забудьте включить аннотации в вашей конфигурации проекта.

Вы всегда можете выполнять еще более сложные проверки, используя синтаксис выражений.

Ответ 3

Другой способ (по крайней мере, от Symfony 2.3) - использовать простой @Assert\IsTrue:

class Conference
{
    //...

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

    //...
}

Как ссылка, документация.

Ответ 4

Это еще проще, поскольку версия 2.4. Все, что вам нужно сделать, это добавить этот метод в свой класс:

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 возвращает построитель, который имеет несколько других методов, которые помогут вам настроить ограничение (например, параметры и перевод).