symfonysymfony-3.4

Symfony - Form with multiple entity objects


I'm running Symfony 3.4 LTS and I have an entity Attribute:

<?php

class Attribute
{

    private $id;
    private $code;
    private $value;
    private $active;

    // My getters and setters

Below the database table:

enter image description here

I would like to get, in a form, all the rows with code == 'productstatus'. I tried:

<?php

$attributes = $this->getDoctrine()->getRepository(Attribute::class)->findBy(['code' => 'productstatus']);
// $attributes contains array with 3 objects 'Attribute'
$form = $this->createFormBuilder($attributes);
$form->add('value', TextType::class);
$output = $form->getForm()->createView();

If I dump() the $output var in Twig:

enter image description here

... I'm unable to make a loop to display the 3 fields with values.

{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}

Result :

enter image description here

My goal is to allow the user to edit all the values of a specific attributes in the same form (or multiple forms, but in the same page). I already tried with CollectionType without success.


Solution

  • I found a solution: create 2 nested forms and use CollectionType. Hope it helps.

    <?php
    
    // Controller
    
    $attributes = $this->getDoctrine()->getRepository(Attribute::class)->findBy(['code' => 'productstatus']);
    $form = $this->createForm(AttributeForm::class, ['attributes' => $attributes]);
    
    // AttributeForm
    
    $builder
        ->add('attributes', CollectionType::class, [
            'entry_type' => AttributeValueForm::class,
            'allow_add' => true,
            'by_reference' => false,
            'allow_delete' => true,
        ]);
    
    // AttributeValueForm
    
    $builder
        ->add('value', TextType::class, ['label' => false, 'required' => false])
        ->add('active', CheckboxType::class, ['label' => false, 'required' => false])
    
    // Twig view
    
    {{ form_start(form) }}
        {% for attribute in form.attributes.children %}
            <tr>
                <td>{{ form_widget(attribute.value) }}</td>
                <td>{{ form_widget(attribute.active) }}</td>
            </tr>
        {% endfor %}
    {{ form_end(form) }}