Symfony 表单 - 在 CollectionType 中的子条目类型中访问实体

Posted

技术标签:

【中文标题】Symfony 表单 - 在 CollectionType 中的子条目类型中访问实体【英文标题】:Symfony form - Access Entity inside child entry Type in a CollectionType 【发布时间】:2012-04-01 04:42:24 【问题描述】:

我正在尝试访问 FormBuilder 内的父 CollectionType 中给定嵌入表单的实体:

父类型

Class ParentType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder->add('children', CollectionType::class, array(
            'entry_type' => ChildType::class
        );
    

子类型

class ChildType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $child = $builder->getData(); // this returns null
    

    public function getDefaultOptions(array $options)
    
        return array(
            'data_class' => 'Vendor\Bundle\Entity\Child',
        );
    

虽然这在正常形式下工作,但 $child 被返回为 null。如何访问ChildType 中的Child 实体?

【问题讨论】:

【参考方案1】:

答案在于使用事件监听器来监听PRE_SET_DATA事件。

它将向您的闭包传递一个 FormEvent 类,其中包含表单和绑定到它的数据。

public function buildForm(FormBuilderInterface $builder, array $options)

    $builder->addEventListener(FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($builder)
        
            $form = $event->getForm();
            $child = $event->getData();

            if ($child instanceof Child) 

                // Do what ever you like with $child entity data

            
        
    );

【讨论】:

要问一个显而易见的问题,您的父实体中是否肯定有任何用于表单数据的 Bars?您可以通过 var_dumping 您的父表单类型中的数据来检查 bar 集合吗? 太好了,谢谢!这非常有效,也让我找到了我忽略的文档中的部分:How to Dynamically Generate Forms Using Form Events 太棒了!我很高兴它对你有用。与 symfony 1 相比,其中一些东西看起来相当神秘,但慢慢地我开始看到隧道尽头的曙光 :) 这在 Symfony2.6 中不起作用。没有 DataEvent (你仍然可以 google 并找到一个包含课程详细信息的页面,但该课程不包含在 Symfony2 中) 在 symfony 2.6 上。事件类是Symfony\Component\Form\FormEvent【参考方案2】:

这是基于user1207727的更详细的解决方案。

父类型

class FrontentStatsInputFormType extends AbstractType


    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder
            ->add('records', CollectionType::class, array(
                'entry_type' => FrontendStatsRecordType::class,
                'allow_add' => false,
                'allow_delete' => false,
                'label' => null,
            ))
        ;
    

    public function configureOptions(OptionsResolver $resolver)
    
        $resolver->setDefaults(array(
            'data_class' => null
        ));
    

儿童类型

class FrontendStatsRecordType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options)
    
        $builder->addEventListener(FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($builder)
            
                $form = $event->getForm();
                $child = $event->getData();

                if ($child instanceof StatsRecord) 

                    // Do what ever you like with $child entity data
                    // $child->getSomeValue();

                    $form->add('value', TextType::class);
                
            
        );

    

    public function configureOptions(OptionsResolver $resolver)
    
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\StatsRecord',
        ));
    


在控制器中创建表单

public function indexAction(Request $request, InputForm $inputForm) 

    $data = array();

    foreach ($inputForm->getStatsTemplates() as $template) 
        $statsRecord = new StatsRecord();
        $data['records'][] = $statsRecord;
    


    $form = $this->createForm('AppBundle\Form\FrontentStatsInputFormType', $data);
    $form->handleRequest($request);


    if ($form->isSubmitted() && $form->isValid()) 

        $em = $this->getDoctrine()->getManager();

        // Get entries and persist them in the database
        $records = $form->get('records')->getData();
        foreach ($records as $record) 
            $em->persist($record);
        

        $em->flush();

        return $this->redirectToRoute('frontend_index');
    

    return $this->render('frontend/showInputForm.html.twig', array(
        'inputForm' => $inputForm,
        'form' => $form->createView(),
    ));

【讨论】:

以上是关于Symfony 表单 - 在 CollectionType 中的子条目类型中访问实体的主要内容,如果未能解决你的问题,请参考以下文章

Symfony / Sonata Admin:编辑表单上的列表表单

Symfony 表单 - 内部带有复选框的集合类型

Symfony2:集合中的单选按钮

Symfony 4:调用 getter 后,Doctrine2 LAZY Fetch Collection 仍然为空

Symfony2 - 动态生成的表单在编辑表单时不起作用

重新验证表单 Symfony 3 [关闭]