Aujourd’hui en développant, je suis tombé sur un cas de figure assez basique mais qui fait péter une grosse erreur à Doctrine.
Admettons que vous avez deux entités liées par un ManyToOne. On va reprendre l’exemple du précédent billet en disant que l’entité principale est Codeur et l’entité propriétaire de la relation est Pantalon. Vous codez une méthode permettant d’ajouter, d’un coup, plusieurs pantalons à un codeur (par exemple via un formulaire d’ajout de pantalon comportant un bouton « + »). Dans votre traitement vous obtiendrez quelque chose comme ceci (si vous êtes bons 😉 :
Jusque là, tout va bien. Maintenant imaginez que vous devez ajouter 2 000 pantalons d’un coup (genre le mec vient d’acheter un magasin avec son salaire de codeur). Vous êtes consciencieux et prenez en exemple le paragraphe de Doctrine sur le Batch Processing. Vous modifiez donc votre boucle afin de faire flush + clear tous les 100 pantalons.
Et là, c’est le drame. Votre script vous balance une superbe erreur du genre :
A new entity was found through the relationship ‘Petegore\DemoBundle\Entity\Pantalon#codeur’ that was not configured to cascade persist operations for entity: pete_gore. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={« persist »}).
En fait, ce que Doctrine ne précise pas dans sa doc, c’est que sa solution fonctionne bien si l’on n’utilise aucune entité actuellement récupérée via l’EntityManager. Autrement dit : dans notre cas, le $codeur étant récupéré via l’EM, il est lié à celui-ci par référence. En faisant un clear(), on le « perd » ; de ce fait, au flush suivant, Doctrine nous dit « hey, je le connais pas moi, ce codeur !« .
La solution est très simple, bien qu’elle soit un peu crade : récupérer le user après chaque clear :
Je vous sens dubitatif, genre « c’est quoi ce problème bidon, Doctrine n’a pas pensé à ça ?!« . Essayez, vous verrez !
Merci cet article me fut d’une grande aide 🙂