Symfony:如何在Twig模板循环中为每个Ring实体添加复选框
问题
我是PHP和Symfony的初学者,尝试从数据库中展示Ring实体的每条数据,并在每个Ring条目末尾添加复选框,但当前Twig模板仅在第一个Ring条目显示复选框,请问如何实现所有Ring条目都显示复选框?
原控制器代码
public function testPage(Request $request) { $ring = $this->ringRepository->customFindAll(); $jewel = $this->ringJewelRepository->customFindAll(); $custom = $this->customRingRepository->customFindAll(); $form = $this->createFormBuilder($ring) ->add('active', CheckboxType::class, [ 'label'=>'Selection', 'required'=>false ]) ->getForm(); $form->handleRequest($request); return [ 'rings'=>$ring, 'jewels'=>$jewel, 'custom' => $custom, 'form'=>$form->createView() ]; }
原Twig模板代码
{% for ring in rings %} <div> <div class="text-center"> <p>Ring Name: {{ ring.ring_name }}</p> <p>Ring Type: {{ ring.ring_type }}</p> {{ form_start(form) }} {{ form_widget(form.active) }} {{ form_end(form) }} </div> <div class="text-center"> <a href="{{ url('update_ring', {'id': ring.id}) }}" class="btn-basic">Update Ring</a> </div> </div> {% endfor %}
问题原因
你把整个Ring集合直接传给表单构建器,表单只会生成一个active字段。在Twig循环中,每次渲染form.active都是同一个DOM元素(id重复),浏览器只会显示第一个,后续的会被忽略。
解决方案
提供两种可行的实现方式,按需选择:
方案一:使用集合类型(CollectionType)推荐
这种方式符合Symfony表单的设计规范,适合批量处理选中状态。
修改后的控制器代码
public function testPage(Request $request) { $rings = $this->ringRepository->customFindAll(); $jewel = $this->ringJewelRepository->customFindAll(); $custom = $this->customRingRepository->customFindAll(); // 初始化选中状态数组,键为Ring的ID,默认未选中 $selectedRings = array_fill_keys( array_map(fn($ring) => $ring->getId(), $rings), false ); $form = $this->createFormBuilder(['selected_rings' => $selectedRings]) ->add('selected_rings', CollectionType::class, [ 'entry_type' => CheckboxType::class, 'entry_options' => [ 'label' => 'Selection', 'required' => false, ], 'allow_add' => false, 'allow_delete' => false, ]) ->getForm(); $form->handleRequest($request); // 处理表单提交,获取选中的Ring ID if ($form->isSubmitted() && $form->isValid()) { $data = $form->getData(); $selectedIds = array_keys(array_filter($data['selected_rings'])); // 这里可以添加批量操作逻辑,比如批量删除、更新等 } return [ 'rings' => $rings, 'jewels' => $jewel, 'custom' => $custom, 'form' => $form->createView() ]; }
修改后的Twig模板代码
{{ form_start(form) }} {% for ring in rings %} <div> <div class="text-center"> <p>Ring Name: {{ ring.ring_name }}</p> <p>Ring Type: {{ ring.ring_type }}</p> {# 渲染对应Ring的复选框 #} {{ form_widget(form.selected_rings[ring.id]) }} </div> <div class="text-center"> <a href="{{ url('update_ring', {'id': ring.id}) }}" class="btn-basic">Update Ring</a> </div> </div> {% endfor %} {{ form_end(form) }}
方案二:为每个Ring创建独立字段
适合数据量较小的场景,直接为每个Ring生成单独的复选框字段。
修改后的控制器代码
public function testPage(Request $request) { $rings = $this->ringRepository->customFindAll(); $jewel = $this->ringJewelRepository->customFindAll(); $custom = $this->customRingRepository->customFindAll(); $formBuilder = $this->createFormBuilder(); // 遍历每个Ring,添加独立的复选框字段 foreach ($rings as $ring) { $formBuilder->add('ring_' . $ring->getId(), CheckboxType::class, [ 'label' => 'Selection', 'required' => false, 'data' => false, // 默认未选中 ]); } $form = $formBuilder->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $data = $form->getData(); $selectedIds = []; foreach ($data as $key => $isSelected) { if ($isSelected) { // 提取Ring的ID $selectedIds[] = str_replace('ring_', '', $key); } } // 处理选中的Ring } return [ 'rings' => $rings, 'jewels' => $jewel, 'custom' => $custom, 'form' => $form->createView() ]; }
修改后的Twig模板代码
{{ form_start(form) }} {% for ring in rings %} <div> <div class="text-center"> <p>Ring Name: {{ ring.ring_name }}</p> <p>Ring Type: {{ ring.ring_type }}</p> {# 渲染对应Ring的独立复选框 #} {{ form_widget(form['ring_' ~ ring.id]) }} </div> <div class="text-center"> <a href="{{ url('update_ring', {'id': ring.id}) }}" class="btn-basic">Update Ring</a> </div> </div> {% endfor %} {{ form_end(form) }}
内容的提问来源于stack exchange,提问作者maz32
相关产品推荐
相关产品推荐

