Search code examples
phpjquerysymfonyone-to-manyformbuilder

Symfony: Form Builder doesn't get OneToMany inputs


So I have OneToMany relation between two entities and I have created the related form to it, but it seems that the FormBuilder, after sending data, doesn't see the children of the entity.
Parent class:

class Parent{
   /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */

   private $id;

   /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
   private $name;

   /**
     * @ORM\OneToMany(targetEntity="Child",mappedBy="parent",cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=false)
     */
   private $children;
}

Child class:

class Child{
    /**
      * @var int
      *
      * @ORM\Column(name="id", type="integer")
      * @ORM\Id
      * @ORM\GeneratedValue(strategy="AUTO")
      */
    private $id;
     /**
      * @var string
      *
      * @ORM\Column(name="name", type="string", length=255)
      */
    private $name;
    /**
     * @ORM\ManyToOne(targetEntity="Parent", inversedBy="children")
     */
    private $parent;
}

This is FormTypes:

class ParentType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name')
            ->add('children', CollectionType::class, array(
            'entry_type' => ChildType::class,
            'allow_add' => true

        ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Bundle\Entity\Parent'
        ));
    }

}

Child FormType:

class ChildType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name');
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Bundle\Entity\Child'
        ));
    }
}

After that I have created my form inside the controller like this:

function saveAction(Request $request){
    $parent = new Parent();
    $form = $this->createForm('Bundle\Form\ParentType', $parent);
    $form->handleRequest($request);
    if ($form->isSubmitted()) {
            //--after submitted the form I just want to display the children
            die(var_dump($parent->getChildren()));


        }
}

Of course I'm creating the children using jquery from data-prototype provided by symfony's FormBuilder, but the form doesn't see them !!
What am I missing here ?


Solution

  • It could be because your 'setters' are not being called.

    Try adding by_reference and setting it to false like this:

    class ParentType extends AbstractType
    {
        /**
         * {@inheritdoc}
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('name')
                ->add('children', CollectionType::class, array(
                'entry_type' => ChildType::class,
                'allow_add' => true,
                'by_reference' => false
    
            ));
        }
    
        /**
         * {@inheritdoc}
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'Bundle\Entity\Parent'
            ));
        }
    
    }
    

    I don't have time to actually test your code. However, you shouldn't have to put parent in your child form. So your child formType should look like this:

    class ChildType extends AbstractType
    {
        /**
         * {@inheritdoc}
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('name')      ;
    
        }
    
        /**
         * {@inheritdoc}
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'Bundle\Entity\Child'
            ));
        }
    }
    

    Hope it helps.