2016-04-01 51 views
1

我需要创建一个表单类型,它将创建某个实体的多个记录。Symfony2创建表单类型以添加​​多个相同类型的记录

我想出了创建一个父窗体类型,然后在里面添加一个集合。此父类型不绑定到任何实体,但是子类型为。问题是,当我处理请求时,我得到一个空的数据对象。

这里是我的父类型:

class ChallengeCollectionType extends AbstractType { 

    /** 
    * {@inheritdoc} 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('email_invitations', CollectionType::class, [ 
      'entry_type' => EmailInvitationType::class 
     ]); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'csrf_protection' => false 
     )); 
    } 

} 

我的孩子类型:

class EmailInvitationType extends AbstractType { 

    /** 
    * {@inheritdoc} 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $builder->add('email', EmailType::class); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class'  => Challenge::class, 
      'csrf_protection' => false 
     )); 
    } 

} 

这是我如何处理我的数据控制器:

public function inviteEmailAction(Request $request){ 

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

     $form->handleRequest($request); 

     dump($form->getData()); 
     dump($form->get('email_invitations')->getData()); 
     die(); 
} 

我在提交数据POST请求(这是API并且没有HTML表单)如下:

challenge_collection[email_invitations][0][email] = "[email protected]" 
challenge_collection[email_invitations][1][email] = "[email protected]" 

并且Controller为所有转储返回空[]。

其实我已经找到一种解决方法,但它看起来不错:

 $data = ['email_invitations' => [new Challenge(), new Challenge()]];   

     $form = $this->createForm(ChallengeCollectionType::class, $data); 

     $form->handleRequest($request); 

,这将工作,所以我要送实体的类型的空对象的数组Get请求处理。

甚至这样说:

$data = ['email_invitations' => []]; 

    if(!empty($request->request->get('challenge_collection'))){ 
     if(!empty($request->request->get('challenge_collection')['email_invitations'])){ 
      for($i = 0; $i < count($request->request->get('challenge_collection')['email_invitations']); $i ++){ 
       $data['email_invitations'][] = new Challenge(); 
      } 
     } 
    } 

应该有更好的方式来做到这一点,请大家帮我找到它。

回答

0

也许你应该试着在你的控制器是这样的:

$invitations = $this->getDoctrine()->getRepository('yourInvitationEntityClass')->findAll());   
$form = $this->createForm(ChallengeCollectionType::class, $invitations); 

你可以在这里找到解释:

http://symfony.com/doc/current/cookbook/form/form_collections.html

One form with all row of one entity

+0

谢谢回复!我担心的是,在这种情况下,findAll()可能会返回数千条记录,是否会向数据库运行繁重的请求以获取一些我实际上不会使用的数据?在这种情况下,创建一组空实体的循环看起来更有效 –

+0

Hi @Vladimir Mikhaylovskiy findAll()仅仅是一个例子。您可以在您的存储库中制作自己的请求并使用它。但如果仅仅是有效地创造新的,那不是一个好的方法:c)。在这种情况下,您应该尝试使用Prototype:http://symfony.com/doc/currentbook/form/form_collections.html#allowing-new-tags-with-the-prototype – lemairep

+0

据我所知,Prototype仅用于对于前端,但我不关心它,因为我正在构建API。在标签的例子中有getTags(),它返回与实体相关的所有标签。但我没有一个实体在我的情况。 –

1

你应该尝试使用allow_addallow_delete选项收集字段类型。 See the Collection field type documentation

此外,这对于父实体与子实体有一个mapped-by关联很重要,这会让您获得控制器中的ArrayCollection对象中的子对象。

此外,如果您想根据请求自动保存/删除它们,则需要实施'by_reference false and set association with cascade-persist and cascade-remove`。

我已经使用collection字段类型与API多次,它的工作就像魅力。让我知道你是否需要进一步的解释。

相关问题