【问题标题】:Symfony2 invalid dynamic form with no errorSymfony2 无效的动态表单没有错误
【发布时间】:2013-10-14 08:42:01
【问题描述】:

我在 symfony2 上遇到了动态表单的问题。我正在尝试为提交的表单生成一些字段。换句话说,用户输入一些值,提交表单,根据这些值,我的动态字段被添加到同一个表单中(显然,这是第二次显示)。为此,我使用了食谱中的这个例子:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data

所以,这是我的 FormationType 类

class FormationType extends AbstractType
{

private $em;
private $context;

public function __construct($em, $context) {
    $this->em = $em;
    $this->context = $context;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name')
        ->add('date')
        ->add('type', 'choice', array(
            'mapped' => false,
            'choices' => Formationlist::getTypeTypes(false),
            'empty_value' => false,
        ))
        ->add('cost')
        ->add('travelCost')
        ->add('maximum')
        ->add('location')
        ->add('schedule')
    ;

    $formModifier = function(FormInterface $form, $type) {
        $formationList = $this->em->getRepository('CoreBundle:FormationList')->findBy(array("year" => 1, "type" => $type));

        $form->add('formationList', 'entity', array(
            'label'=> 'Titre formation', 
            'choices' => $formationList, 
            'class' => 'CoreBundle:FormationList', 
            'property' => 'title',)
                );

        };


    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event) use ($formModifier) {

            $data = $event->getForm();
            $type = $data->get('type')->getData();

            $formModifier($event->getForm(), $type);

        }
    );

    $builder->get('type')->addEventListener(
        FormEvents::POST_SUBMIT,
        function(FormEvent $event) use ($formModifier) {

            $type = $event->getForm()->getData();
            $formModifier($event->getForm()->getParent(), $type);
        }
    );
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'EXAMPLE\CoreBundle\Entity\Formation'
    ));
}

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

所以,这两个 addEventListener 工作得很好。第一次显示我的表单时,formModifier 中的字段未按预期加载。我的控制器类如下:

public function createAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $contextSrv = $this->get('example.service.context');
    $context = $contextSrv->getContext();

    $entity  = new Formation();
    $form = $this->createForm(new FormationType($em, $context), $entity);
    $form->bind($request);

    if ($form->isValid()) {

        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('formation_show', array('id' => $entity->getId())));
    }

    return array(
        'entity' => $entity,
        'form'   => $form->createView(),
    );
}

由于我的一个动态字段不能为空,所以第一次提交表单时,它是无效的。因此,FormationType 被第二次加载。这意味着,如果字段“类型”被填充,我的 formModifier() 函数可以加载动态字段(formationList)。在那之前,一切都很好,我得到了我的新领域。

但是,在表单上“提交”第二次之后……什么也没有发生。页面刚刚重新加载,并没有显示任何错误。

我用

检查了表单内容
var_dump($request->request->get('example_corebundle_formationtype'));

-> 每个字段(包括动态字段)都填充了有效值。

我也试试这个:

foreach($form->all() as $item) {
       echo $item->getName();
        var_dump($item->getErrors());
}

-> 这些行没有显示任何错误。但是,表单永远无效。

var_dump($form->isValid());

-> 它返回 false。所以表格无效。

最后,如果我删除整个动态部分,我的表单就可以工作了。 我不明白出了什么问题。表单没有显示错误,并且 csrf 令牌似乎正确。我错过了什么 ?感谢您的帮助。

【问题讨论】:

  • 只是一个猜测,当你删除这行代码时,你能用萤火虫检查 类型的值是否相同:'choices' => $formationList, from your form $formModifier ?
  • 嗯...我不明白你的意思。我从 $formModifier 中删除了 'choices' => $formationList,但字段“type”没有发生任何事情。这是预期的,因为“类型”是没有动态值的选择。 formationList 字段过去是,现在仍然是一个列表(
  • 内的 应该是 FormationList 类的有效 id(无论您指定什么主键),否则 $form->isValid() 将为 false。这是我的观点,但我很确定列表 $formationList 做得很好,因此它应该有正确的 id。这只是一个疯狂的猜测。
  • 添加一个 {{ form_errors(form) }} 以在视图上打印所有表单错误。也许您在实体函数上有一些验证器?
  • 似乎错误冒泡已禁用。你试过设置error_bubbling => true吗?此外,您指的是 2.4 文档。您使用的是 Symfony 2.4.x 吗?如果是这样,Profiler 有一个 Form 部分。跟踪发生的事情可能很有用。

标签: php forms symfony dynamic


【解决方案1】:

我知道这有点过时,但在 Google 上的排名很高。

getErrors() 方法只返回表单的全局错误而不是底层字段的错误消息,在表单中使用嵌入表单时,您需要 getErrors(true) 或更复杂的方法。请参阅:https://knpuniversity.com/blog/symfony-debugging-form-errors 了解更多信息。

【讨论】:

    【解决方案2】:

    您的表单中可能存在验证错误。

    而不是您对 Form::getErrors() 的复杂调用——它不是完全递归的,因为任何比第二级更深的字段的错误都不会显示——你应该使用 Form::getErrorsAsString().

    这是 Symfony 开发人员为像您这样的开发人员创建的调试方法,试图了解验证错误在复杂表单中的位置。

    如果应该显示但没有显示错误,这可能是表单主题错误。创建自定义表单主题时,开发人员可能会覆盖或忘记显示字段的错误块。

    问题的另一个可能来源是表单的一般显示。如果您使用 {{ form_widget(form) }} 显示您的表单,那么任何冒泡到顶部表单的错误都将永远不会显示。然后确保您使用 {{ form_row(form) }} 代替。

    【讨论】:

    • 很高兴知道,getErrorsAsString,谢谢你的提示!不幸的是,它没有显示任何错误。每个字段只有“无错误”...我还使用 row_form 而不是 form_widget 来获得相同的结果。而且由于我不为此表单使用自定义主题......这不应该是原因。但是您的建议将帮助我找出问题所在!
    • 但这太荒谬了。如果你自己检查 Form::isValid() 的基本定义,这个方法只是递归地检查是否存在错误。如果 Form::getErrorsAsString() 什么都不返回,那么 isValid() 应该为真,句号。您是否使用自定义 isValid() 方法?您确定在表单绑定后进行检查和转储吗?
    • 也有可能多了一个字段。
    【解决方案3】:

    我也遇到过几次这个问题。

    在我的例子中,我以 JSON 格式发布数据,所以我必须做一个具有高优先级的请求侦听器,它将 json 数据转换为普通的 POST 数据,在 $request->request 中可用。

    在 $form 无效且 post 数据为空时也没有错误的情况下,尝试转储 $request->request->all() 以查看是否有数据。

    【讨论】:

      猜你喜欢
      • 2016-04-25
      • 2012-06-27
      • 1970-01-01
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多