我在表单的事件订阅者中有一个preSubmit事件,对于特定情况,我想在表单字段中添加错误。订阅者中的方法如下:
public function onPreSubmit(FormEvent $event)
{
$sourceData = $event->getData();
$form = $event->getForm();
$identifier = &$sourceData['identifier'];
if ($identifier) {
if ($this->identifierIsUrl($identifier)) {
$parser = $this->getIdParser();
$identifier = $parser->getIdentifier($identifier);
if (is_null($identifier)) {
$form->get('identifier')->addError(new FormError('You have either entered an incorrect url for the source or it could not be parsed'));
}
}
$event->setData($sourceData);
}
}
但是,当我在视图中打印表单错误时,它是空的。是否可以在preSubmit事件中执行此操作?我看错了吗?
答案 0 :(得分:7)
此问题与Symfony\Component\Form\Form::submit
方法有关,该方法会删除PRE_SUBMIT
事件后分配的所有表单字段特定错误。
在Form::submit
期间,它会迭代所有表单子对象(这些对象也是其他答案所指出的Form
个对象)并单独调用它们的submit
方法。导致在父{q} 1}事件期间添加的表单元素错误被重置为空数组。
这就是为什么您可以在父PRE_SUBMIT
事件中使用$form->addError()
或将表单元素设置为PRE_SUBMIT
,它将显示为父表单错误,但不会显示为特定表单元件。
这是在不查看Symfony Forms的整个代码库的情况下发生的示例。
error_bubbling => true
因此导致
class Form
{
public function addError($error)
{
if($this->parent && $this->config->getErrorBubbling()) {
$this->parent->addError($error); //element had error_bubbling => true, attach the error to the parent.
} else {
$this->errors[] = $error; //add it to the current object's errors array
}
}
public function submit()
{
$this->errors = array(); //resets the errors of the current object
$this->preSubmitEvent();
foreach($this->children as $child) {
$child->submit(); //errors in child object are reset
}
}
}
要解决此问题,您可以直接向表单元素添加Form:
submitMethod:
preSubmitEvent
children:
submitMethod:
preSubmitEvent
事件,以验证该元素并向其中添加错误。
PRE_SUBMIT
然后相应地更改public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('identifier', Form\TextType::class);
//...
$builder->get('identifier')->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'validateIdentifier']);
}
方法。
onPreSubmit
答案 1 :(得分:0)
如果您查看Form::submit(),应该可以看到错误在之前重置 PRE_SUBMIT
数据被调度。此外,Validation Listener不会重置表单上的错误,而Violation Mapper仅会将错误添加到表单中。而AFIK没有任何监听器可以重置表单的错误。所以也许你做错了什么。
答案 2 :(得分:0)
错误可能不会在您的布局中显示。
要进行调试,请确保您的表单实际上因自定义检查而无效(如果您显示控制器我可以帮助您使用实际代码)。
如果这实际上是您的问题,您可能需要在字段定义中添加error_bubbling => true
。