Создайте форму, имеющую флажок для каждого объекта в коллекции доктрины

Я показываю таблицу html для фильтрованной коллекции объектов, и я хочу отображать флажок в каждой строке как часть формы, которая добавит выбранные объекты в сеанс var.

Я думаю, что каждый флажок должен иметь идентификатор сущности в качестве его значения, и я получу массив идентификаторов из данных поля формы (ok, поэтому значение должно быть косвенным ref для объекта, но для для простоты).

Я попытался создать форму Type с одним типом типа объекта, сопоставленным с свойством id объекта и вложенным в другую форму. Тип, у которого есть поле типа коллекции.

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

Когда форма визуализируется, для поля идентификатора есть отдельная метка, но нет виджетов.

Возможно ли использовать этот объект только для полей типа сущности и типа? Если да, то что я могу сделать неправильно?

Ответ 1

Я думаю, что это ответит на ваш вопрос.

Забудьте 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]) }}

    {# ... #}

Ответ 2

Если кто-то ищет решение для 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();
    }

Ответ 3

Я создаю комплект symfony для визуализации коллекции объектов как таблицы флажка настраиваемым способом. Хотя с тех пор, как был задан этот вопрос, прошло некоторое время, я надеюсь, что это может помочь другим с такой же проблемой.