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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9723713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 07:30:27  来源:igfitidea点击:

Symfony form - Access Entity inside child entry Type in a CollectionType

phpdoctrine-ormsymfonysymfony-forms

提问by Nick

I'm trying to access the entity for a given embedded form in the parent CollectionTypeinside FormBuilder:

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

ParentType

父类型

Class ParentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('children', CollectionType::class, array(
            'entry_type' => ChildType::class
        );
    }
}

ChildType

儿童类型

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',
        );
    }
}

While this works in a normal form, $childis being returned as null. How can I access the Childentity inside ChildType?

虽然这在正常形式下有效,但$child被返回为 null。如何访问Child里面的实体ChildType

回答by user1207727

The answer lies in using Event Listenerswhich listen for the PRE_SET_DATAevent.

答案在于利用事件监听器该监听PRE_SET_DATA事件。

It will pass your closure a FormEventclass which contains both the form and the data being bound to it.

它会给你的闭包传递一个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

            }
        }
    );
}

回答by segli

This is a more detailed solution based on user1207727.

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

Parent Type

父类型

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
        ));
    }
}

Child Type

儿童类型

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',
        ));
    }

}

Create form in controller

在控制器中创建表单

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(),
    ));
}