构建一个表单,其中包含一个doctrine集合中每个实体的复选框

时间:2013-02-01 02:31:24

标签: symfony symfony-forms symfony-2.2

我正在为过滤的实体集合显示一个html表格,我希望在每一行中显示一个复选框作为表单的一部分,该表单将选定的实体添加到会话变量中。

我认为每个复选框都应该有实体ID作为其值,我将从表单字段数据中获取一组id(确定,因此该值应该是对实体的间接引用,但是对于为了简单起见。)

我尝试使用单个实体类型字段创建表单Type,映射到实体的id属性并嵌入到具有集合类型字段的另一个表单Type中。

class FooEntitySelectByIdentityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('foo_id', 'entity', array(
            'required'  => false,
            'class'    => 'MeMyBundle:FooEntity',
            'property' => 'id',
            'multiple' => true,
            'expanded' => true
        ));
    }

# ...

class FooEntitySelectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('identity', 'collection', array(
            'type'   => new FooEntitySelectByIdentityType,
            'options'  => array(
                'required' => false,
                'multiple' => true,
                'expanded' => true,
                'attr'     => array('class' => 'foo')
            ),
        ));
    }

# ...

并在控制器中创建表单,其中包含一组实体作为初始数据

$form = $this
    ->createForm(
        new \Me\MyBundle\Form\Type\FooEntitySelectionType,
        $collection_of_foo
    )
    ->createView()
;

呈现表单时,标识字段只有一个标签,但没有小部件。

甚至可以以这种特殊方式使用实体和集合类型字段吗? 如果是这样,我可能做错了什么?

3 个答案:

答案 0 :(得分:8)

我认为这会回答你的问题。

忘记FooEntitySelectionType。向property_path添加FooEntitySelectByIdentityType字段选项,并将data_class选项设置为null

class FooEntitySelectByIdentityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('foo_id', 'entity', array(
            'required'      => false,
            'class'         => 'MeMyBundle:FooEntity',
            'property'      => 'id',
            'property_path' => '[id]', # in square brackets!
            'multiple'      => true,
            'expanded'      => true
        ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'      => null,
            'csrf_protection' => false
        ));
    }

# ...

并在您的控制器中构建FooEntitySelectByIdentityType

$form = $this
    ->createForm(
        new \Me\MyBundle\Form\Type\FooEntitySelectByIdentityType,
        $collection_of_foo
    )
    ->createView()
;

然后在接收POSTed数据的控制器操作中:

$form = $this
    ->createForm(new \Me\MyBundle\Form\Type\FooEntitySelectByIdentityType)
;
$form->bind($request);
if ($form->isValid()) {
    $data = $form->getData();
    $ids  = array();
    foreach ($data['foo_id'] as $entity) {
        $ids[] = $entity->getId();
    }
    $request->getSession()->set('admin/foo_list/batch', $ids);
}

最后,在你的树枝模板中:

{# ... #}
{% for entity in foo_entity_collection %}
    {# ... #}

    {{ form_widget(form.foo_id[entity.id]) }}

    {# ... #}

答案 1 :(得分:3)

如果有人正在为Symfony寻找解决方案> = 2.3

你必须改变这个:

    $data = $form->getData();
    $ids  = array();
    foreach ($data['foo_id'] as $entity) {
        $ids[] = $entity->getId();
    }

到此:

    $data = $form['foo_id']->getData();
    $ids = array();
    foreach ($data as $entity) {
        $ids[] = $entity->getId();
    }

答案 2 :(得分:2)

我创建了一个symfony bundle,用于以可配置的方式呈现实体集合作为复选框表。虽然问这个问题已经有一段时间了,但我希望这可以帮助其他人解决同样的问题。