Symfony2 无效的动态表单,没有错误


Symfony2 invalid dynamic form with no error

我在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工作得很好。第一次显示我的表单时,表单修饰符中的字段未按预期加载。我的控制器类如下:

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。这意味着,如果字段"type"被填充,我的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());

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

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

我知道

这有点过时了,但在谷歌上排名很高。

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

表单中的某个位置可能存在验证错误。

而不是对 Form::

getErrors(( 的复杂调用 - 这不是完全递归的,因为任何深度超过第 2 级的字段的错误都不会显示 - 你应该使用 Form::getErrorsAsString((。

这是Symfony为像您这样的开发人员创建的调试方法,试图了解复杂形式的验证错误可能在哪里。

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

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

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

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

一种情况是,当发布数据为空时,$form无效并且没有错误,请尝试转储 $request->request->all(( 以查看您是否有数据。