Symfony2 Doctrine2 Many-To-Many relation with two Owning Sides and Doctrine cmd line tools
The default behavior of a many-to-many association will have an owning side and an inverse side. If you are dealing with the owning side of the association, then the association will be handled by the ORM. However if you are dealing with the inverse side, it is up to you to explicitly handle this.
In your case, you have mappedBy="groups"
in the $services
property of the ServiceGroup
class. What this means is that, this association between the Service and the ServiceGroup is maintained by the $groups
property of the Service
entity. So, Service
becomes the owning side of this association.
Now, say you are creating or updating a Service
entity. Here when you add ServiceGroup
entities to this Service
entity, and persist the Service
entity, all the entities and the relevant associations are automatically built by the ORM.
But, if you are creating or updating a ServiceGroup
entity, when you add Service
entities to it, and persist the ServiceGroup
entity, the association is not built by the ORM. Here as a workaround, you have to explicitly add the ServiceGroup
entity to the Service
entity.
// in ServiceGroup.phppublic function addService(Service $service){ $service->addServiceGroup($this); $this->services->add($service);}// in Service.phppublic function addServiceGroup(ServiceGroup $group){ if (!$this->serviceGroups->contains($group)) { $this->serviceGroups->add($group); }}
Things to keep in mind
- Make sure that you initialize your
$services
and$serviceGroups
to doctrine collections at the time of entity creation i.e. in the constructors. - You need to have
'by_reference' => false
in yourservices
field in the FormType for theServiceGroup
.
Reference:http://symfony.com/doc/2.8/cookbook/form/form_collections.html
Example of ensuring that the owning side (Service) always gets updated.
class ServiceGroup{ public function addService($service) { if (!$service) return; $this->services[] = $service; $service->addGroup($this); }}
Have you tried coding it with an intermediate entity and many to one associations instead?
While it might not be what you want to have, it might provide insights on how to make it work with many to many.
(And frequently you end up realizing that the intermediate entity deserves to be there because of some attributes of the association.)