Bonjour,
Effet recherché:
1. vider une collection doctrine (One-to-many)2. ajouter de nouveaux membres à cette collection
Code : Sélectionner tout - Visualiser dans une fenêtre à part $myEvent->getRegistrations()->clear()3. enregistrer en base de donnée:
Code : Sélectionner tout - Visualiser dans une fenêtre à part $myEvent->addRegistration($myRegistration)
Code : Sélectionner tout - Visualiser dans une fenêtre à part $em->persist($myEvent); $em->flush();
Constatation:
Après de nombreux essais, lors du flush final, l'insertion de la nouvelle Registration se fait avant le delete des autres Registrations de la collection.
Apparemment, doctrine2 ne respecte pas l'ordre dans lequel sont effectuées ces opérations si on ne met qu'un seul flush à la fin (en 3), et il faut mettre en plus un flush entre 1) et 2) pour que ça fonctionne.
Question:
Est-ce que ma constation est juste?
Mais dans ce cas, est-ce qu'il ne serait pas logique que doctrine gère ce worflow de façon transparente, et réalise les opérations dans le bonne ordre lors du flush en 3) ?
Détail de mon test:
- Mes relations: Event <= One-to-Many => Registrations <=Many-to-One => User
- Ma DB contient déjà des Registrations pour l'Event traité ici
- j'ai une contrainte Unique sur la propriété User de mes entités Registration (colonne event_user)
- Raison pour laquelle je souhaite avoir qu'un seul flush: pendant que je travaille sur l'entité en mémoire, je souhaite par la suite faire un detach pour récupérer l'ancienne entité dans la base et examiner les différences entre l'ancienne et la nouvelle.
Avec le code suivant, j'obtiens une exception due à la violation sur la clef étrangère user, ce qui indique que les Registrations n'ont pas été supprimées en base de donnée avant l'insertion (la base de donnée contient déjà des Registrations, dont une pour l'utilisateur 1 que j'ajoute aprés):
Définition de la relation:An exception occurred while executing 'INSERT INTO Registration (createdAt, updatedAt, numparticipant, numqueuedparticipant, organizer, user_id, event_id) VALUES (?, ?, ?, ?, ?, ?, ?)' with params ["2014-07-12 20:32:26", "2014-07-12 20:32:26", 10, 0, 1, 1, 114]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '114-1' for key 'event_user'
Voilà mon code de test:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Cpt\EventBundle\Entity\Event: type: entity oneToMany: registrations: targetEntity: Registration mappedBy: event indexBy: user_id cascade: ["persist","detach","merge"] orphanRemoval: true Cpt\EventBundle\Entity\Registration: type: entity event: targetEntity: Event inversedBy: registrations joinColumn: name: event_id referencedColumnName: id onDelete: CASCADE
le removeRegistration de l'entité event:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 public function testAction() { try{ // Récupérer l'Event 114 déjà en base de donnée $event = $this->getEventManager()->getEventById(114); // Supprimer toutes les registrations (j'ai essayé avec la boucle foreach mais sans le collection->clear() et inversement, et avec les deux foreach($event->getRegistrations() as $registration){ $event->removeRegistration($registration); $this->getDoctrine()->getManager()->remove($registration); } $event->getRegistrations()->clear(); // Persist l'Event - J'ai essayé avec et sans ce persist $this->getDoctrine()->getManager()->persist($event); // Créer une nouvelle Registration et l'ajouter à la collection $user = $this->getUserManager()->findUserBy(Array("id" => 1)); $registration = $this->getRegistrationManager()->CreateRegistration($event, $user, 10, true ); $event->addRegistration($registration); // Persist et Flush l'Event $this->getDoctrine()->getManager()->persist($event); $this->getDoctrine()->getManager()->flush(); } catch (\Exception $e) { throw $e; } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 public function removeRegistration(\Cpt\EventBundle\Entity\Registration $registrations) { $this->registrations->removeElement($registrations); $registrations->setEvent(null); }
Partager