jureispro
jureispro

Reputation: 1402

Symfony 3 expected "Doctrine\Common\Collections\ArrayCollection" given ... when using OneToMany

I have a problem with this error:

Expected argument of type "AppBundle\Entity\BusVehiclesAmenities", "Doctrine\Common\Collections\ArrayCollection" given

EDIT 3

After few comments I applied suggestions and error is gone now (remove ArrayCollection from bus vehicles amenities Entity, removed setting bus vehicles amenities entity from controller and removed ORM Join columns on all mapped entites)

Now I have this error:

The association AppBundle\Entity\BusVehiclesAmenities#bus refers to the inverse side field AppBundle\Entity\BusVehicles#busVehiclesAmenities which does not exist.

Mapped entities

Bus vehicles:

/* @ORM\OneToMany(
     *     targetEntity="BusVehiclesAmenities",
     *     mappedBy="bus",
     *     fetch="EXTRA_LAZY",
     *     orphanRemoval=true,
     *     cascade={"persist"}

     * )
     *
     */

    private $busVehiclesAmenities;

bus vehicles amenities entity:

private $bus;

    /**
     *
     * @ORM\ManyToOne(targetEntity="Amenities", inversedBy="amenities")
     * @ORM\JoinColumn(name="amenities_id", referencedColumnName="id")
     *
     */

I am using Collection of Forms to create OneToMany relationship. Problem is when I adding new data I got this error.

Does someone knows where is the problem?

CODE: Bus Entity (Parent)

/**
     * @ORM\OneToMany(targetEntity="BusVehiclesAmenities", mappedBy="bus", cascade={"persist", "remove"}, fetch="EAGER", orphanRemoval=true)
     * @ORM\JoinColumn(name="bus_id", referencedColumnName="id", onDelete="CASCADE")
     *
     */

private $busVehiclesAmenities;

    public function __construct()
    {

        $this->busVehiclesAmenities = new ArrayCollection();
    }


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Add busVehiclesAmenities
     *
     * @param \AppBundle\Entity\BusVehiclesAmenities busVehiclesAmenities
     * @return BusVehicles
     */
    public function addBusVehiclesAmenities(BusVehiclesAmenities $busVehiclesAmenities)
    {

         if ($this->busVehiclesAmenities->contains($busVehiclesAmenities)) {
             return;
         }
        $this->busVehiclesAmenities->add($busVehiclesAmenities);
        $busVehiclesAmenities->addBus($this);

        return $this;
    }

    /**
     * Set busVehiclesAmenities
     *
     * @param \AppBundle\Entity\BusVehiclesAmenities busVehiclesAmenities
     * @return BusVehicles
     */
    public function setBusVehiclesAmenities(BusVehiclesAmenities $busVehiclesAmenities)
    {

         $this->busVehiclesAmenities = $busVehiclesAmenities;

        return $this;
    }

    /**
     * Remove busVehiclesAmenities
     *
     * @param \AppBundle\Entity\BusVehiclesAmenities $busVehiclesAmenities
     * @return BusVehicles
     */
    public function removeBusVehiclesAmenities(BusVehiclesAmenities $busVehiclesAmenities)
    {
        if (!$this->busVehiclesAmenities->contains($busVehiclesAmenities)) {
            return;
        }
        $this->busVehiclesAmenities->removeElement($busVehiclesAmenities);
        $busVehiclesAmenities->removeBus($this);

        return $this;



    }

Amenity Entity (Child)

/**
     *
     * @ORM\ManyToOne(targetEntity="BusVehicles", inversedBy="busVehiclesAmenities")
     * @ORM\JoinColumn(name="bus_id", referencedColumnName="id")
     *
     */
    private $bus;

    public function __construct()
    {
        $this->bus = new ArrayCollection();
    }


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }


    /**
     * @param BusVehicles $busVehicles
     */

    public function addBus(BusVehicles $busVehicles)
    {
        if ($this->bus->contains($busVehicles)) {
            return;
        }
        $this->bus->add($busVehicles);
        $busVehicles->addBusVehiclesAmenities($this);
    }

    /**
     * @param BusVehicles $busVehicles
     */
    public function removeBus(BusVehicles $busVehicles)
    {
        if (!$this->bus->contains($busVehicles)) {
            return;
        }
        $this->bus->removeElement($busVehicles);
        $busVehicles->removeBusVehiclesAmenities($this);
    }

EDIT 1:

I removed ArrayCollection from BusVehiclesAmenitites Entity but I still got same error when I submit form.

EDIT 2:

Added forms

BusVehicles Form Type

<?php

namespace AdminBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;




class BusVehiclesType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('licencePlate')
            ->add('chassisNumber')
            ->add('manufacturer')
            ->add('busVehiclesAmenities', CollectionType::class, array(
                'entry_type'   => BusVehiclesAmenitiesType::class,
                'prototype' => true,
                'allow_add' => true,
                'allow_delete' => true,
                'by_reference' => false,
            ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\BusVehicles',
            'cascade_validation' => true,

        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'adminbundle_busvehicles';
    }


}

BusVehiclesAmenities Form Type

    <?php

namespace AdminBundle\Form\Type;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use AppBundle\Entity\BusVehiclesAmenities;
use Symfony\Component\OptionsResolver\OptionsResolver;


class BusVehiclesAmenitiesType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('price', NumberType::class, array(

            ))
            ->add('amenities', EntityType::class, array(
                'class' =>'AppBundle:Amenities',
                'choice_label' => 'name',
            ))

        ;

    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => BusVehiclesAmenities::class
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_busvehiclesamenities';
    }


}

Controller.

/**
     * @Template
     */
    public function newAction(Request $request)
    {
        $bus = new BusVehicles();
        $busAmenities = new BusVehiclesAmenities();
        //   $this->getDoctrine()->getManager()->persist($busAmenities);
        $bus->setBusVehiclesAmenities($busAmenities);
        $form = $this->createForm(BusVehiclesType::class, $bus);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            $em = $this->getDoctrine()->getManager();
            /*$form->get('busVehiclesAmenities')->getData()->map(
                function ($amenities) use ($em, $bus) {

                    $bus->setBusVehiclesAmenities($amenities);
                    $em->persist($amenities);
                }
            );*/
            $em->persist($bus);

            $em->flush();

            // Adding flash message to our user

            $this->addFlash('success', 'admin.bus.created');


            //  return $this->redirectToRoute('bus_add');

        }
        return [
            'form' => $form->createView(),
        ];
    }

Upvotes: 0

Views: 4904

Answers (3)

BILL WAGNER
BILL WAGNER

Reputation: 155

I have run into a similar problem to yours. What I did to fix the situation is remove the JoinColumn. It is actually redundant. It's one of those "magic" things about Symfony which can get annoying IMHO. Just make sure that your OneToMany annotation correctly points back to your ManyToOne. Here's an example-- this is in my User.php Entity:

/**
 * @ORM\OneToMany(targetEntity="AppBundle\Entity\UserStats", mappedBy="user")
 */
private $userStats;

And this is in the entity being joined (UserStats.php):

/**
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User",
 *     inversedBy="userStats")
 *
 */
private $user;

As you can see, there is no JoinColumn, and everything works beautifully as a result. I hope this helps you. :)

Make sure that you use the proper path as I have above, i.e.

* (targetEntity="AppBundle\Entity\User", inversedBy="userStats")

Upvotes: 2

DFayet
DFayet

Reputation: 881

BusVehiclesAmenities->bus is an object, not a collection. The line $this->bus = new ArrayCollection(); has no reason to exist in your child entity.

You want to achieve ManyToOne, a Many (amentities) aka an ArrayCollection in a object (bus) which is a single object.

Edit

In your controller you do the following

$bus->setBusVehiclesAmenities($busAmenities);

This is not needed. The form will handle the collection by himself. magic

Your error may come from this call, but this is because you are trying to say arrayCollection = object which is not possible.

  public function setBusVehiclesAmenities(BusVehiclesAmenities $busVehiclesAmenities)
    {
        // ArrayCollection = Object
        $this->busVehiclesAmenities = $busVehiclesAmenities;
        return $this;
    }

You can either try to do setBusVehiclesAmenities(ArrayCollection $busVehiclesAmenities) or Collection, I don't know, or remove the setBusVehiclesAmenities method. (personally I would remove the method)

Also you should check your getter/setter for bus in your child, this time your variable is a single object, juste do getBus() and setBus($bus), not add and remove.

Hope this may helps you

Upvotes: 0

michail_w
michail_w

Reputation: 4481

From Amenity Entity (Child) remove this part of code:

public function __construct()
{
    $this->bus = new ArrayCollection();
}

It should solve your problem, if forms have been defined right way.

Explanation - bus in this entity is the owning side of OneToMany relation. It's always one, it can't be a collection.

Upvotes: 0

Related Questions