Symfony 如何从控制器动态设置表单的级联验证

Symfony 如何从控制器动态设置表单的级联验证,symfony,symfony-forms,symfony-2.3,Symfony,Symfony Forms,Symfony 2.3,我的表单如下所示: class CpanelRetailerForm extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name', 'text', array( 'attr' => array(

我的表单如下所示:

class CpanelRetailerForm extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
                ->add('name', 'text', array(
                    'attr' => array(
                        'class' => 'text-input',
                        'size' => '50'
                    ),
                    'required' => false
                ))
                ->add('email', 'email', array(
                    'attr' => array(
                        'class' => 'text-input',
                        'size' => '50'
                    ),
                    'required' => false
                ))
                ->add('addUser', 'checkbox', array(
                    'label' => 'Add User account',
                    'required' => false,
                    'mapped' => false
                ))
                ->add('user',new CpanelUserForm());
    }

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

    public function getName() {
        return 'retailer';
    }    
}
我想根据addUser字段是选中还是未选中,从控制器动态设置此行

cascade_validation' => true
这是我的控制器代码:

$form = $this->createForm(new CpanelRetailerForm(), new Retailer());
    $form->
    if ($this->getRequest()->isMethod('POST')) {
        $form->bind($this->getRequest());
        if ($form->get('addUser')->getData()) {
         // then set the cascade_validation to true here
        }
}
如何在控制器内部执行此操作

我的尝试: 在我的表单类中添加了此行:

 $builder->addEventListener(
            FormEvents::POST_SUBMIT, function(FormEvent $event) {
                $form = $event->getForm();
                $addUser = $form->get('addUser')->getData();
                $validation = false;
                if ($addUser) {
                    $validation = true;
                }
                $resolver = new OptionsResolver();
                $resolver->setDefaults(array(
                    'cascade_validation' => $validation
                ));
                $this->setDefaultOptions($resolver);
            }
    );
class TestType extends AbstractType {

    /**
     * @var boolean
     */
    private $myOption;

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $this->myOption = false;

        $builder
            ->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) {
                dump('formEvents::PRE_SET_DATA');
            })
            ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
                dump('FormEvents::POST_SET_DATA');
            })
            ->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
                dump('FormEvents::PRE_SUBMIT');
            })
            ->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) {
                dump('FormEvents::SUBMIT');
            })
            ->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
                dump('formEvents::POST_SUBMIT');
            })
            ->add('name', TextType::class)
            ->add('send', SubmitType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setRequired(array(
            'my_option'
        ));
        $resolver->setDefaults(array(
            'my_option' => $this->setMyOption()
        ));
    }

    /**
     * @return bool
     */
    public function setMyOption() {
        dump($this->myOption);
        return $this->myOption;
    }
}
这对我不起作用。虽然我在$addUser中接收数据,但没有添加cascade\u验证

如何在控制器内部执行此操作? 你不能!答案很简单。让我们看一下下面的简单表单类:

 $builder->addEventListener(
            FormEvents::POST_SUBMIT, function(FormEvent $event) {
                $form = $event->getForm();
                $addUser = $form->get('addUser')->getData();
                $validation = false;
                if ($addUser) {
                    $validation = true;
                }
                $resolver = new OptionsResolver();
                $resolver->setDefaults(array(
                    'cascade_validation' => $validation
                ));
                $this->setDefaultOptions($resolver);
            }
    );
class TestType extends AbstractType {

    /**
     * @var boolean
     */
    private $myOption;

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $this->myOption = false;

        $builder
            ->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) {
                dump('formEvents::PRE_SET_DATA');
            })
            ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
                dump('FormEvents::POST_SET_DATA');
            })
            ->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
                dump('FormEvents::PRE_SUBMIT');
            })
            ->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) {
                dump('FormEvents::SUBMIT');
            })
            ->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
                dump('formEvents::POST_SUBMIT');
            })
            ->add('name', TextType::class)
            ->add('send', SubmitType::class);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver) {
        $resolver->setRequired(array(
            'my_option'
        ));
        $resolver->setDefaults(array(
            'my_option' => $this->setMyOption()
        ));
    }

    /**
     * @return bool
     */
    public function setMyOption() {
        dump($this->myOption);
        return $this->myOption;
    }
}
让我们了解如何在控制器内渲染和处理窗体:

public function formAction(Request $request) {

    $form = $this->createForm(TestType::class);

    dump('calledCreateForm');

    $form->handleRequest($request);

    if($form->isSubmitted() && $form->isValid()) {
        dump('finished');
        dump($form->getData());
        die();
    }

    return $this->render('@TestPra/Test/test_form.html.twig', array(
        'form'  => $form->createView()
    ));
    
}
提交表单后,您将获得以下输出顺序:

  • $this->setMyOption()
    null
  • FormEvents::预设置数据
  • FormEvents::POST\u SET\u DATA
  • 调用创建表单
  • FormEvents::PRE_SUBMIT
  • FormEvents::提交
  • FormEvents::POST_SUBMIT
  • 完成

  • allways被调用的第一件事是
    configureOptions
    ,因为在调用
    handleRequest
    之前,您没有任何已填充表单的数据,所以在不操作Symfonys表单组件的情况下,无法更改allready创建表单的选项。

    为什么不根据值动态修改表单类型改为
    addUser
    ?请您解释一下如何使用您的方式这是一个很好的起点: