【问题标题】:Symfony2: my form returns false from isValid() but empty array for getErrors() from unique constraint conditionSymfony2:我的表单从 isValid() 返回 false,但 getErrors() 从唯一约束条件返回空数组
【发布时间】:2013-07-13 14:18:19
【问题描述】:

我有一个客户实体,它只有一个唯一的电子邮件字段。我正在尝试编辑客户的电子邮件并且验证工作正常。但是我的控制器中有这个:

public function updateAction(Request $request, $id) {
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('AcmeDemoBundle:Customer')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Customer entity.');
    }


    $editForm = $this->createForm(new CustomerType(), $entity);
    $editForm->bind($request);
    if ($editForm->isValid()) {
        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('ticket_result'));
    }
    var_dump($editForm->getErrors());

    return $this->render('AcmeDemoBundle:Customer:edit.html.twig', array(
                'entity' => $entity,
                'edit_form' => $editForm->createView(),
    ));
}

var_dump 返回一个空数组,但验证器设置了一个唯一错误,$editForm->isValid() 返回 false。有没有办法在验证期间检查控制器中的特定错误,你也能解释为什么它返回一个空的错误数组吗?基本上,如果出现该错误,我想提供“合并”选项。

编辑:这是表单类型:

namespace Acme\DemoBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CustomerType extends AbstractType {


    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('email', 'email', array('required'=>true))
        ;

    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\Customer',
            'cascade_validation' => true,
        ));
    }

    public function getName() {
        return 'acme_demobundle_customertype';
    }
}

还有树枝模板:

{% extends 'AcmeDemoBundle::layout.html.twig' %}
{% block body -%}
    <h1>Customer edit</h1>



  <form action="{{ path('customer_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(edit_form) }}>
        <input type="hidden" name="_method" value="PUT" />
        {{ form_widget(edit_form) }}
        <p>
            <button type="submit">Edit</button>
        </p>
    </form>

{% endblock %}

这是我的验证:

Acme\DemoBundle\Entity\Customer:
    constraints:
      - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: 
          fields: email
          message: "A customer under that email address already exists"

    properties:
        email:
            - Email: ~

【问题讨论】:

  • 您的客户类型是否有任何子表单?
  • 请展示你的模板
  • 我更新了帖子并添加了验证、模板和表单类型

标签: forms symfony unique validation


【解决方案1】:

如果您使用 Symfony 2,则出于调试目的,您可以使用 $form-&gt;getErrorsAsString() 而不是 $form-&gt;getErrors()。*

引用自this answer

$form-&gt;getErrorsAsString() 只能用于调试表单...它 将包含不是这种情况的每个子元素的错误 $form->getErrors().


更新 1:

“对于较新的 Symfony 版本,您必须改用 $form-&gt;getErrors(true, false);。第一个参数对应于deep,第二个参数对应于flatten”(参见@Roubi 的评论)

【讨论】:

  • getErrorsAsString 自 2.5 版起已弃用,将在 3.0 版中删除。改用 getErrors()} 并将结果转换为字符串。
  • @DénesPapp 传递可选的布尔参数以级联任何子表单 $form->getErrors(true);
  • 对于较新的 Symfony 版本,您必须改用 $form-&gt;getErrors(true, false);。第一个参数对应于 deep,第二个参数对应于 flatten
【解决方案2】:

好的,在这里找到答案:

Symfony2 invalid form without errors

事实证明,每个表单子项都有自己单独的错误。当做一个 var_dump 的

$editForm->getChildren()['email']->getErrors()

我明白了:

array (size=1)
  0 => 
    object(Symfony\Component\Form\FormError)[531]
      private 'message' => string 'A customer under that email address already exists' (length=50)
      protected 'messageTemplate' => string 'A customer under that email address already exists' (length=50)
      protected 'messageParameters' => 
        array (size=0)
          empty
      protected 'messagePluralization' => null

我仍然想知道如何在不解析错误消息字符串的情况下确定错误是由于唯一冲突引起的。

【讨论】:

  • $editForm-&gt;getErrors(true) 现在将递归地从子级返回表单错误(从 2.5 开始)。
【解决方案3】:

以下解决方案适用于我:

$form->getErrors(true)

【讨论】:

    【解决方案4】:

    您可以在每个字段上使用 error_bubbling 将错误冒泡到您的 $form。

    如果没有,也可以foreach通过错误

    foreach ($children as $child) {
                if ($child->hasErrors()) {
                    $vars = $child->createView()->getVars();
                    $errors = $child->getErrors();
                    foreach ($errors as $error) {
                        $this->allErrors[$vars["name"]][] = $this->convertFormErrorObjToString($error);
                    }
                }
    }
    

    【讨论】:

      【解决方案5】:

      在 Symfony 2.3 中,你可以使用这个:

      if ($form->isValid()){
          # Code...
      } else {
          foreach ($form->getIterator() as $key => $child) {
              if ($child instanceof Form) {
                  foreach ($child->getErrors() as $error) {
                      $errors[$key] = $error->getMessage();
                  }
              }
          }
      }
      

      这将为您提供一个包含子级错误的数组 ($errors)。

      【讨论】:

        【解决方案6】:

        当表单提交但无效时,您可以尝试使用dump 函数。我是这样用的

        if($form->isSubmited() && $form->isValid()){
           //SAVE TO DATABASE AND DO YOUR STUFF
        }else if($form->isSubmited()){
          //SUBMITED BUT WITH ERRORS
           dump($form->getErrors(true));
           die();
        
        }
        

        请注意,这仅用于调试目的,它将显示您的表单、其中的数据以及任何字段可能存在的所有错误。 在生产模式下,您应该将错误返回给视图并将它们显示给用户。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-24
          • 2020-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多