Search code examples
phpsymfonydoctrine

Update association with doctrine and Symfony 2.7


I want to know if it exists a better way to update association in doctrine from the inversed side entity, in this case it's a many to many type, but it may be another one.

This is the method I used:

$entity = $em->getRepository('MyBundle:MyEntity')->find($id);

foreach ($entity->getAssociation() as $value) {
    $entity->removeAssociation($value);
}
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
        foreach ($entity->getAssociation() as $value) {
            $entity->addAssociation($value);
        }
        $em->flush();
}

I think that it's not a good approach, because I want to update (so remove and add) only the association that I select or unselect in my form, not every element of the array. So I made a service with an update function:

    public function updateCollection(&$newEntity, $newCollection, $oldCollection, $contains, $add, $remove) {

    foreach ($oldCollection as $value) {
        $item = call_user_func(array($newCollection, $contains), $value);
        if(!$item){
            call_user_func( array($newEntity, $remove), $value );
        }
    }

    foreach ($newCollection as $value) {
        $item = call_user_func(array($oldCollection, $contains), $value );
        if(!$item){
            call_user_func( array($newEntity, $add), $value );
        }
    }
    
}

And I call this method with this:

    $oldAssociation = clone $entity->getAssociation();
    
    $editForm = $this->createEditForm($entity);
    $editForm->handleRequest($request);

    if ($editForm->isValid()) {

      $this->get('service_update')->updateCollection(
        $entity,
        $entity->getAssociation(),
        $oldAssociation,
        'contains',
        'addAssociation',
        'removeAssociation'
  );

  $em->flush();

}

But I think that this method is more time expensive than the first one, but it only remove and add elements from the array for which the association has been changed. I don't know what is the best way to do this, maybe none of the two. Can you bring me on the right way please? Thank you and sorry for my bad English


Solution

  • I was doing it in the wrong way. I found the best solution ever to update the inversed side of a relation in this post: https://knpuniversity.com/screencast/collections/saving-inverse-side-collection

    I don't know why but I didn't found that before, I advise people to use that solution for a multiple choices of entity type elements.