Symfony 验证 - 在自定义验证行为中设置属性路径
Posted
技术标签:
【中文标题】Symfony 验证 - 在自定义验证行为中设置属性路径【英文标题】:Symfony validation - set the property path in custom validation act 【发布时间】:2021-04-09 04:08:42 【问题描述】:我想问一下,如何在违反约束时设置属性路径。
到目前为止,我正在做一个普通的验证,比如(用户是一个普通的实体,有一些预定义的约束——它们按方面工作):
$validationErrors = $this->validator->validate($user);
接下来,在用户注册控制器方法中,我正在尝试手动方法(因为将约束直接放在用户实体中会导致每次都验证密码)
我在需要时验证密码,如下所示:
$passwordLength = mb_strlen($password);
$passwordMinLength = new Assert\Length(null, 8);
$passwordErrors = $this->validator->validate($passwordLength, [ $passwordMinLength ]);
然后,我将结果添加到现有集合中:
$validationErrors->addAll($passwordErrors);
但是当我检查密码产生的违规时,没有在其上定义 propertyPath。我构建了一个自定义树枝扩展,它依赖于设置的属性路径。我如何告诉它在 $passwordErrors
数组上使用名为“密码”的 propertyPath?
希望你能理解我的问题:)。
最好的问候!
罗伯
编辑: 我找到了适合我的解决方法。我敢肯定,这不是解决我的问题的最佳方式,但由于我已经为这件小事浪费了几个小时,我决定宁愿选择解决方法,而不是在这件小事上花更多时间。
我的解决方法 虽然我无法访问私有属性propertyPath,但我想为每个违规设置propertyPath,我通过以下方式解决了它:
一开始我创建了一个闭包函数:
$closure = Closure::bind(function (ConstraintViolation $violation)
$violation->propertyPath = 'password';
, null, ConstraintViolation::class);
然后我为每次违规调用它:
foreach ($passwordErrors as $violation)
// $violation->propertyPath = 'password';
$closure($violation);
【问题讨论】:
【参考方案1】:如果我理解正确,您需要一个类约束验证器。 您需要将此添加到约束类:
public function getTargets()
return self::CLASS_CONSTRAINT;
因此,验证器的validate()
方法获取一个对象作为其第一个参数,atPath()
方法用于定义与验证错误关联的属性。
class ProtocolClassValidator extends ConstraintValidator
public function validate($protocol, Constraint $constraint)
if ($protocol->getFoo() != $protocol->getBar())
$this->context->buildViolation($constraint->message)
->atPath('foo')
->addViolation();
文档:https://symfony.com/doc/current/validation/custom_constraint.html
【讨论】:
【参考方案2】:我刚刚发现了如何修改现有的违规行为 而不是使用
$validationErrors->addAll($passwordErrors);
在您的自定义验证器中,使用此
/** @var ConstraintViolationInterface $violation */
foreach ($validationErrors as $violation)
$this->context->buildViolation($violation->getMessage())
->atPath('password')
->addViolation();
【讨论】:
以上是关于Symfony 验证 - 在自定义验证行为中设置属性路径的主要内容,如果未能解决你的问题,请参考以下文章
Symfony2 测试中的伪造身份验证 - 控制器上的 get('security.context')->getToken() 返回的令牌与 TestCase 中设置的令牌不同