Как проверить свойство, зависящее от другого свойства в Symfony 2
Можно ли проверить свойство класса модели, зависящее от другого свойства того же класса?
Например, у меня есть этот класс:
class Conference
{
/** $startDate datetime */
protected $startDate;
/** $endDate datetime */
protected $endDate;
}
и я хочу, чтобы Symfony 2.0 подтверждал, что $startDate
должен быть после $endDate
.
Это возможно по аннотации или мне нужно сделать это вручную?
Ответы
Ответ 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
возвращает построитель, который имеет несколько других методов, которые помогут вам настроить ограничение (например, параметры и перевод).