将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint
Posted
技术标签:
【中文标题】将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint【英文标题】:Pass custom parameters to custom ValidationConstraint in Symfony2 【发布时间】:2013-03-15 07:30:55 【问题描述】:我正在 Symfony2 中创建一个表单。该表单仅包含一个book
字段,允许用户在Books
实体列表之间进行选择。我需要检查所选的Book
是否属于我的控制器中的Author
。
public class MyFormType extends AbstractType
protected $author;
public function __construct(Author $author)
$this->author = $author;
public function buildForm(FormBuilderInterface $builder, array $options)
$builder->add('book', 'entity', array('class' => 'AcmeDemoBundle:Book', 'field' => 'title');
// ...
我想在提交表单后检查所选的Book
是否由我的控制器中的$author
写入:
public class MyController
public function doStuffAction()
$author = ...;
$form = $this->createForm(new MyFormType($author));
$form->bind($this->getRequest());
// ...
不幸的是,我找不到任何方法来做到这一点。我尝试按照The Cookbook 中的说明创建自定义验证器约束,但是虽然我可以通过将验证器定义为服务来将EntityManager
作为参数传递,但我无法将$author
从控制器传递到验证器约束。
class HasValidAuthorConstraintValidator extends ConstraintValidator
private $entityManager;
public function __construct(EntityManager $entityManager)
$this->entityManager = $entityManager;
public function validate($value, Constraint $constraint)
$book = $this->entityManager->getRepository('book')->findOneById($value);
$author = ...; // That's the data I'm missing
if(!$book->belongsTo($author))
$this->context->addViolation(...);
This solution 可能正是我正在寻找的那个,但我的表单没有绑定到实体,也不应该是(我从 getData()
方法获取数据)。
我的问题有解决方案吗?这应该是常见的情况,但我真的不知道如何解决。
【问题讨论】:
【参考方案1】:好吧,我对表单/验证组件不太熟悉,但您可以使用 Hidden field 和作者的姓名/ID 并检查它是否相同:
class MyFormType extends AbstractType
protected $author;
public function __construct(Author $author)
$this->author = $author;
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('book', 'entity', array('class' => 'AcmeDemoBundle:Book', 'field' => 'title');
->add('author_name', 'hidden', array(
'data' => $this->author->getId(),
))
;
// ...
【讨论】:
感谢您的回答,但出于安全原因,我认为我不能这样做。实际上,用户可以更改表单中的author
字段以匹配任何其他作者,从而绕过限制。
感谢您编辑我的问题,我不知道 Markdown 语法高亮 :)【参考方案2】:
首先将 setAuthor 方法添加到您的约束,然后调整 validate 方法。诀窍是确定调用它的最佳位置。
目前尚不清楚您如何将验证器绑定到您的图书。你是在使用validation.yml 还是在表单内部做一些事情?
【讨论】:
感谢您的回答,将作者注入约束就可以了!我试图将作者注入无效的 ValidatorConstraint !【参考方案3】:在 Cerad 的帮助下,我终于弄明白了。要注入需要从ConstraintValidator::validate()
方法访问的自定义参数,您需要在Constraint
中将它们作为options 传递。
public class HasValidAuthorConstraint extends Constraint
protected $author;
public function __construct($options)
if($options['author'] and $options['author'] instanceof Author)
$this->author = $options['author'];
else
throw new MissingOptionException("...");
public function getAuthor()
return $this->author;
并且,在 ConstraintValidator 中:
class HasValidAuthorConstraintValidator extends ConstraintValidator
private $entityManager;
public function __construct(EntityManager $entityManager)
$this->entityManager = $entityManager;
public function validate($value, Constraint $constraint)
$book = $this->entityManager->getRepository('book')->findOneById($value);
$author = $this->constraint->getAuthor();
if(!$book->isAuthor($author))
$this->context->addViolation(...);
最后但同样重要的是,您必须将参数传递给验证器:
public function buildForm(FormBuilderInterface $builder, array $options)
$builder->add('book', 'entity', array(
'class' => 'AcmeDemoBundle:Book',
'field' => 'title',
'constraints' => array(
new HasValidAuthorConstraint(array(
'author' => $this->author
))
)
));
【讨论】:
请注意,在 Symfony 2.7 中,自定义参数不是直接在 $options 数组中找到的,而是在一个 'value' 键中。所以对于这个例子,你会从 $options['value']['author'] 获得作者。如果您使用注释声明断言,您将编写如下内容:@CustomAssert\CustomDateTime("dateFormat" : Enum::DATE_FORMAT) 您应该定义 $author 属性 public 以便您可以在构造函数中调用parent::__construct($options);
。【参考方案4】:
接受的答案对我使用 Symfony 框架 2.1 版 不起作用。我就是这样解决的。
class CustomConstraint extends Constraint
public $dependency;
public $message = 'The error message.';
class CustomConstraintValidator extends ConstraintValidator
public function validate($value, Constraint $constraint)
if (!$constraint->dependency->allows($value))
$this->context->addViolation($constraint->message);
class CustomFormType extends AbstractType
private $dependency;
public function __construct(Dependency $dependency)
$this->dependency = $dependency;
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('field', 'type', array(
'constraints' => array(
new CustomConstraint(array('dependency' => $this->dependency))
)
));
【讨论】:
以上是关于将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint的主要内容,如果未能解决你的问题,请参考以下文章
如何将自定义注释中的参数传递给库中的 WebSecurityConfigurer