php - Symfony 2 - 在 preSubmit 事件订阅者上向表单元素添加错误

标签 php symfony doctrine-orm

我在表单的事件订阅者中有一个 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);
    }    
}

但是当我在 View 中打印表单错误时,它是空的。是否可以在 preSubmit 事件中执行此操作?我是不是看错了?

最佳答案

此问题与 Symfony\Component\Form\Form::submit 方法有关,该方法删除了在 PRE_SUBMIT 事件之后指定的所有表单字段特定错误。

Form::submit 期间,它遍历所有表单子(monad)对象(它们本身也是 Form 对象,如其他答案所述)并调用它们的 单独提交方法。导致在父级的 PRE_SUBMIT 事件期间添加的表单元素错误被重置为空数组。

这就是为什么您可以在父 PRE_SUBMIT 事件中使用 $form->addError() 或将表单元素设置为 error_bubbling => true,它将显示为父表单错误,但不会显示到特定的表单元素。

这里是一个例子,说明了在没有查看 Symfony Forms 的整个代码库的情况下会发生什么。

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 方法。

public function validateIdentifier(FormEvent $event)
{ 
    $identifier = $event->getData();
    $element = $event->getForm();
    if ($identifier) {
        if ($this->identifierIsUrl($identifier)) {
            $parser     = $this->getIdParser();
            $identifier = $parser->getIdentifier($identifier);

            if (null === $identifier) {
                $element->addError(new FormError('You have either entered an incorrect url for the source or it could not be parsed'));
            }
        }

        $event->setData($identifier);
    }    
}

关于php - Symfony 2 - 在 preSubmit 事件订阅者上向表单元素添加错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32012510/

相关文章:

php - 多个变量作为表名

mysql - 在 MySQL 中存储 mongoid 或在 mongo 中存储 MySQL 记录 id?

php - 通过关系发现了一个新实体 - 仅从形式

php - Symfony3 : Relation One to Many return empty object

php - 一个实体到多个实体 symfony

php - 如何使用 PHP 和 PDO 正确删除一行

javascript - 鼠标悬停时更改单独 div 中的图像,动态填充图像

php - 在 PHP 中使用默认魔术引号或用户定义的 addslash/stripslash 哪个更好?

symfony - 找不到 Doctrine Query Builder ACOS 函数

php - 无法 Autowiring PasswordHasherInterface