使用Collection Type实现单表单创建多实体的数据获取问题求助
Symfony CollectionType表单子数据获取问题
问题描述
我尝试用CollectionType创建一个批量生成实体的表单,视图功能正常,能添加新的artikel条目,但调用$form['artikelList']->getData()返回空数组,而$form->getData()里能看到artikel的相关数据,该怎么正确获取这部分数据?
相关代码
MultipleFormType文件
/** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('artikelList', CollectionType::class, [ 'entry_type' => ArtikelEmbeddedFormType::class, 'entry_options' => [ 'label' => false ], 'allow_delete' => true, 'allow_add' => true, 'by_reference' => false, 'label' => false, ]) ->add('Speichern', SubmitType::class, [ 'attr' => ['class' => 'btn--red'] ]); }
嵌入式表单EmbeddedFormType文件
/** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder // ... 其他字段 ->add('artikelName', null, ['label' => 'Name', 'attr' => ['pattern' => '[A-Za-z0-9-_ öÖäÄüÜß]+', 'maxlength' => 255]]) ->add('artikelActive', null, ['label' => 'Aktiv']); }
控制器代码
public function createMultipleArtikel(Request $request) { // 创建多个文章 $form = $this->createForm(MultipleArtikelFormType::class, null); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { var_dump($form->getData()); var_dump($form->get('artikelList')->getData()); foreach($form->get('artikelList')->getData() as $artikel) { $this->artikelRepository->update($artikel); $this->get('session')->getFlashBag()->add( 'notice', 'done!' ); } } // ... 视图渲染逻辑 }
解决方案
问题根源是你创建表单时传入了null作为绑定数据,Symfony表单组件会直接将提交数据映射到顶层数组,无法正确填充到子表单的数据对象中。有两种解决方式:
方式一:使用数据载体类(推荐,类型安全)
- 创建数据载体类
// src/Form/Data/MultipleArtikelData.php namespace App\Form\Data; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use App\Entity\Artikel; class MultipleArtikelData { /** @var Collection<int, Artikel> */ private Collection $artikelList; public function __construct() { $this->artikelList = new ArrayCollection(); } public function getArtikelList(): Collection { return $this->artikelList; } public function setArtikelList(Collection $artikelList): void { $this->artikelList = $artikelList; } public function addArtikel(Artikel $artikel): void { if (!$this->artikelList->contains($artikel)) { $this->artikelList->add($artikel); } } public function removeArtikel(Artikel $artikel): void { $this->artikelList->removeElement($artikel); } }
- 绑定数据类到表单
在MultipleFormType中添加configureOptions方法:
public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => \App\Form\Data\MultipleArtikelData::class, ]); }
- 修改控制器初始化代码
public function createMultipleArtikel(Request $request) { $data = new \App\Form\Data\MultipleArtikelData(); $form = $this->createForm(MultipleArtikelFormType::class, $data); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // 直接从数据对象获取,更直观 foreach($data->getArtikelList() as $artikel) { $this->artikelRepository->update($artikel); $this->addFlash('notice', 'done!'); } // 也可以通过子表单获取数据 // foreach($form->get('artikelList')->getData() as $artikel) { ... } } // ... 视图渲染逻辑 }
方式二:用数组初始化表单(快速解决)
如果不想创建数据类,直接用数组初始化表单,指定artikelList为空数组:
public function createMultipleArtikel(Request $request) { $form = $this->createForm(MultipleArtikelFormType::class, ['artikelList' => []]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // 现在可以正常获取子表单数据 foreach($form->get('artikelList')->getData() as $artikel) { $this->artikelRepository->update($artikel); $this->addFlash('notice', 'done!'); } } // ... 视图渲染逻辑 }
内容的提问来源于stack exchange,提问作者K Nugal
相关产品推荐
相关产品推荐

