Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The form's view data is expected to be an instance of MyEntity but is an instance of ArrayCollection

I can create a form which works fine but getting errors when trying to flush data to the database:

The controller action looks like this:

$purchase = new Purchase();
        $form = $this->createFormBuilder($purchase)
            ->add('addresses', AddressType::class)
            ->add('quantity', IntegerType::class)
            ->add('toBeDeliveredAt', DateType::class)
            ->add('comment', TextareaType::class)
            ->add('save', SubmitType::class, array('label' => 'Submit'))
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($purchase);
            $em->flush();
        }

Class AddressType looks like this:

public function buildForm(FormBuilderInterface $builder, array $options)

{
    $builder
        ->add('title', TextType::class)
        ->add('firstname', TextType::class)
        ->add('lastname', TextType::class)
        ->add('street', TextType::class)
        ->add('city', TextType::class)
        ->add('zipcode', TextType::class)
        ->add('country', TextType::class)
        ->add('phone', TextType::class)
        ->add('email', EmailType::class);
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'XxxBundle\Entity\Address'
    ));
}

But that gives me the following error:

The form's view data is expected to be an instance of class XxxBundle\Entity\Address, but is an instance of class Doctrine\Common\Collections\ArrayCollection. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class Doctrine\Common\Collections\ArrayCollection to an instance of XxxBundle\Entity\Address.

If I set the data_class option to null I get

Warning: spl_object_hash() expects parameter 1 to be object, string given

How can I add a view transformer that transforms an instance of class ArrayCollection to an instance of Address?

like image 500
caramba Avatar asked Mar 11 '23 14:03

caramba


1 Answers

Addresses is an array collection so you have to use it as an collection in your form like this :

$builder->add('addresses', CollectionType::class, array(
            'entry_type' => AddressType::class
        ));

Instead of this :

$builder->add('addresses', AddressType::class)

In this way you embed Address Form into Purchase Form

You can see the doc about embed a collection of form here

Explanations (sorry for my bad English) :

You have to think about object.

In your Purchase Entity you have a collection of Address because a Purchase object can have many address that is to say to persist Purchase object you have to give a collection of addresses.

So when you built your Purshase form, Symfony expects an array collection for addresses input. It is what I wrote above. With this, if you are in the case where you want to add a new Purchase object, when you go to view the form, to display fields corresponding to the Address, you have to do this into your form:

    <ul class="addresses">
            {# iterate over each existing address and render these fields #}
            {% for address in form.addresses %}
                <li>{{ form_row(address.title) }}</li>

                 //do this for all the others fields ...

            {% endfor %}
    </ul>

But if you want to add many address dynamically, you have to do 2 things :

First, you have to do add 'allow_add' => true in the form builder

$builder->add('addresses', CollectionType::class, array(
        'entry_type'   => AddressType::class,
        'allow_add'    => true,
    ));

Second, the allow_add also makes a "prototype" variable available to you in the form html generated : this is where Javascript come in :) To do work this, you have to write some Javascript and you can see a good example here

I hope that it's clearer

like image 80
PASTAGA Avatar answered Apr 25 '23 16:04

PASTAGA