I'm working with Symfony 3.1 and Doctrine 2.5.
I setup a manyToMany relationship as I always do :
manyToMany:
placeServices:
targetEntity: Acme\MyBundle\Entity\PlaceService
joinTable:
name: place_place_service
joinColumns:
place_id:
referencedColumnName: id
inverseJoinColumns:
place_service_id:
referencedColumnName: id
And add methods to my Entity
protected $placeServices;
...
public function __construct()
{
$this->placeServices = new ArrayCollection();
}
...
/**
* @return ArrayCollection
*/
public function getPlaceServices(): ArrayCollection
{
return $this->placeServices;
}
/**
* @param PlaceServiceInterface $placeService
* @return PlaceInterface
*/
public function addPlaceService(PlaceServiceInterface $placeService): PlaceInterface
{
if(!$this->placeServices->contains($placeService)) {
$this->placeServices->add($placeService);
}
return $this;
}
/**
* @param PlaceServiceInterface $placeService
* @return PlaceInterface
*/
public function removePlaceService(PlaceServiceInterface $placeService): PlaceInterface
{
if($this->placeServices->contains($placeService)) {
$this->placeServices->removeElement($placeService);
}
return $this;
}
The thing is, when I load my entity, doctrine put a PersistentCollection in the $this->placeServices property. This does not sound like a big problem, except that when I build a form to connect those two entities (a simple multiple checkboxes with symfony form type), when $form->handleRequest() is triggered, Doctrine try to inject the new data in my entity, and throw an error if get/add/remove method are not using ArrayCollection.
I can force my getter/add/remove methods to transforme the PersistentCollection to ArrayCollection (using unwrap method) but then the relations made are not persisted.
I've found a workaround, if I set fetch="EAGER" on the relation the property is initialized with ArrayCollection, and the relation are persisted. But i'm not sure it's a good solution.
Thanks :)
Just use Doctrine\Common\Collections\Collection interface instead of ArrayCollection. ArrayCollection and PersistentCollection implement this interface.
Doctrine uses PersistentCollection for lazy loading entities. You are right, using EAGER is not always a good solution - it can cause perfomance issues.