在 Symfony 中的第一个错误上停止对象属性验证有多漂亮?

Posted

技术标签:

【中文标题】在 Symfony 中的第一个错误上停止对象属性验证有多漂亮?【英文标题】:How beautifully to stop object property validation on the first error in Symfony? 【发布时间】:2019-05-26 21:58:55 【问题描述】:

我有以下代码:

类用户 /** * @Assert\Type(type="string") * @Assert\NotBlank() * @Assert\Email() * @Assert\Length(max=255) */ 公共$电子邮件;

此对象由 API 调用填充。当验证发生并且属性填充数组值而不是字符串时,NotBlank、电子邮件和长度验证继续工作,我得到“UnexpectedTypeException”。

我希望验证系统只是添加一个关于错误值类型的错误并停在那里。

我已经制作了自定义约束验证器

类 ChainConstraintValidator 扩展 ConstraintValidator /** * @inheritdoc */ 公共函数 validate($value, 约束 $constraint) if (!$constraint instanceof ChainConstraint) throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\All'); $上下文 = $this->上下文; $prevCount = $context->getViolations()->count(); $validator = $context->getValidator()->inContext($context); foreach ($constraint->constraints as $constraintStep) $errors = $validator->validate($value, $constraintStep); if ($errors->getViolations()->count() > $prevCount) 休息;

它有效,我这样使用它:

@链约束( @Assert\Type(type="string"), @Assert\NotBlank(), @断言\电子邮件(), @Assert\Length(最大值=255) )

我的项目中有很多这样的课程。有没有更漂亮且需要更少代码的方法来实现这一目标?

【问题讨论】:

我认为这是因为您的设置器中有类型提示。 这个类没有setter只有一个公共字段。 【参考方案1】:

这个呢:

$var = [];

$constraints = [
 new Type(['type'=>'string', 'groups'=> 'first-check']),
 new NotBlank(['groups'=> 'second-check']),
 new Email(['groups'=> 'second-check']),
 new Length(['min'=>2, 'groups'=> 'second-check'])]
    ;

$groups = ['first-check', 'second-check'];
$groupSequence = new GroupSequence($groups);
$error = $validator->validate($var, $constraints, $groupSequence);

if(count($error) > 0) 
    dd($error); // Contains 1 ConstraintViolation (Type) 
 

【讨论】:

是的,您的解决方案是可行的,就我而言,将有 4 个验证组。实际上我有超过 4 个验证规则的模型字段,它需要很多验证代码。但我会尝试这个选项。谢谢 不客气??别忘了接受我的回答 但是,如果该类有多个要验证的属性,每个属性都有“第一次检查”和“第二次检查”约束,那么一旦某个属性通过第一个验证组,那么第二个对于所有其他属性,组的验证也将被跳过。这可能不是所需的行为,因为在这种情况下,违反对另一个属性的“第二次检查”约束不会引发任何错误……任何人都有其他解决方案来仅在属性级别停止验证? (相对于班级级别)【参考方案2】:

Symfony 5.1 开始,Sequentially constraint 可用。

此约束允许您应用一组规则,这些规则应该是 一步一步验证,允许一旦验证中断 提出第一次违规。

【讨论】:

【参考方案3】:

您可能会在这些问题中找到一些信息,这些信息似乎与您想要的行为相似:

Halt subsequent constraints on first failure #2947 [Validator][GroupSequences] GroupSequences still execute next group if first fail #9939

正如这些问题中所述,我认为正确执行此操作的最佳方法是使用group validation,即使在每个断言上都执行此操作似乎有点笨拙。

【讨论】:

据我了解,这是开箱即用的解决方案。虽然它会起作用,但当我对某些模型字段有 5-10 个约束时,我发现这个解决方案(验证组)非常冗长谢谢

以上是关于在 Symfony 中的第一个错误上停止对象属性验证有多漂亮?的主要内容,如果未能解决你的问题,请参考以下文章

Symfony:属性不存在 - 500 内部服务器错误 - ReflectionException

当 Symfony 教义对象的一个​​属性发生变化时更新另一个属性

symfony 发生错误:注意:未定义的属性:::$container

Symfony messenger 工作人员在主管下运行时不会停止

Symfony 3 Doctrine 2中不存在属性

我在 OpenEMR 中的第一个 Symfony 2.4 组件控制器