是否可以验证依赖于同一类的另一个属性的模型类的属性?
例如,我有这个课程:
class Conference
{
/** $startDate datetime */
protected $startDate;
/** $endDate datetime */
protected $endDate;
}
我希望Symfony 2.0验证,$startDate
必须在$endDate
之后。
这可以通过注释来实现,还是我必须手动执行此操作?
答案 0 :(得分:36)
从 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;
}
不要忘记项目配置中的enable annotations。
您可以使用expression syntax始终进行更复杂的验证。
答案 1 :(得分:20)
是的回调验证器: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 :(得分:10)
另一种方式(至少与 Symfony 2.3 一样)是使用简单的@Assert\IsTrue
:
class Conference
{
//...
/**
* @Assert\IsTrue(message = "Startime should be lesser than EndTime")
*/
public function isStartBeforeEnd()
{
return $this->getStartDate() <= $this->getEndDate;
}
//...
}
作为参考,documentation。
答案 3 :(得分:9)
自version 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
method返回一个构建器,其中包含其他一些方法来帮助您配置约束(如参数和转换)。
答案 4 :(得分:2)
更好更清洁的解决方案https://symfony.com/doc/3.4/validation/custom_constraint.html 就是写
要检查实体是否正常,请添加到自定义约束(不是验证器)
protected void configure(HttpSecurity http) throws Exception {
http.logout()
.logoutUrl("/my/logout")
.logoutSuccessUrl("/my/index")
.logoutSuccessHandler(logoutSuccessHandler)
.invalidateHttpSession(true)
.addLogoutHandler(logoutHandler)
.deleteCookies(cookieNamesToClear)
.and()
...
}
允许您使用该实体的实例,而不仅仅是属性值。这样就可以在验证器中编写:
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
最好的部分是您需要在实体类中编写的内容:
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();
}
希望有帮助
答案 5 :(得分:0)
对于日期验证,我们可以简单地使用GreaterThan和GreaterThanOrEqual比较约束。
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── hellokoding
│ │ └── hello
│ │ └── web
│ │ └── YourClass.java
│ ├── resources
│ │ ├── application.properties
│ │ └── logback.xml
│ └── webapp
│ ├── resources
│ │ ├── css
│ │ │ └── bootstrap.min.css
│ │ ├── images
│ │ └── js
│ │ └── bootstrap.min.js
│ └── WEB-INF
│ ├── views
│ │ └── hello.jsp
| ├── appconfig-mvc.xml
│ ├── appconfig-root.xml
│ └── web.xml
└── pom.xml
有关更多信息,请参见validation constraints