Bonjour à tous,

Cela fait maintenant des heures et des heures que je tente de persister une entité sans y parvenir, j'ai l'impression d'avoir tout essayé ...

Pour faire simple, j'ai une entité "CleVersion" :

class CleVersion
{

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="LogicielBundle\Entity\CleVersionLot", mappedBy="cleVersion", cascade={"persist"})
     */
    private $lots;

    ...

Jusque la, pas de soucis. Ensuite, comme vous l'avez vu, j'ai une entité "CleVersionLot" :

class CleVersionLot
{

    /**
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="LogicielBundle\Entity\CleVersion", inversedBy="lots")
     * @ORM\JoinColumn(name="cle_version_id", referencedColumnName="id")
     */
    private $cleVersion;

    /**
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="LogicielBundle\Entity\Lot")
     * @ORM\JoinColumn(name="lot_id", referencedColumnName="id")
     */
    private $lot;

    ...

Comme vous pouvez le voir, cette entité à sa propre clé composée. En fait, il s'agit d'un "ManyToMany" créé manuellement car il y a d'autres champs. J'ai volontairement retiré les get(), set(), add() et remove() pour ne pas alourdir le code sur le forum, néanmoins ils fonctionnent correctement.

J'ai créé un formulaire qui s'affiche bien et qui envoi correctement toutes les données une fois validé :

        $form = $this->createForm('logiciel_cle_form', $cle);
        $this->submit($form);
        if ($form->handleRequest($request)->isValid()) {
            $em = $this->getDoctrine()->getManager();            
            $em->persist($cle);
            $em->flush();

            ...

Lorsque je fais un dump($cle) juste avant le flush(), la totalité de l'arbre s'affiche bien, ce qui semble signifier que les get() et set() sont bien construits. Cependant, j'ai cette erreur :

Entity of type LogicielBundle\Entity\CleVersionLot has identity through a foreign entity LogicielBundle\Entity\CleVersion, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'LogicielBundle\Entity\CleVersionLot'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.

Je comprends bien le problème, lorsqu'il tente d'insérer la clé composée il y a une erreur, mais le "cascade" devrait justement prévenir ce genre d'erreur ... sur certains forums ils recommandent de ne pas mettre la clé composée et de mettre tout simplement un ID(), mais cette solution contournée ne me plait vraiment pas.

Si quelqu'un a une solution ...
Merci beaucoup :)

4 réponses


Bonjour la variable $cle est une instance de CleVersionLot ou CleVersion ?

Salut et merci de ta réponse :)
En fait, $cle est une instance de Cle que je n'ai pas cité pour ne pas alourdir le code, voici pour résumer :
$cle = une Instance de Cle qui a un OneToMany de CleVersion qui a un ManyToMany fait main de CleVersionLot.
Lorsque de mon formulaire je retire CleVersionLot, les deux premières entités s'insèrent bien, le problème vient bien des deux dernières et de la clé composée fait main. :-S

c'est tout à fait normal d'avoir ce genre d'erreur vue que le champ CleVersionLot::$cleVersion ne marie pas avec un type de champ entité, un type de champ entité se réfère déjà à un objet qui lui est liée donc il faut supprimer @ORM\Id

Tu dois d'abord persister le many to one (l'objet de la relation) et ensuite persister l'objet en entier (l'objet de ton formulaire). Il faut aussi appeler la méthode flush juste après le premier persist (celui du many to one). L'objet de ton many to one peut être orphelin.

$monObjetManyToOne = ...
$em->persist($monObjetManyToOne);
$em->flush($monObjetManyToOne);

$monObjetDeBase->addMonObjetManyToOne($monObjetManyToOne);

$em->persist($monObjetDeBase);
$em->flush();

Il se peut que des fois du dois appelé dans ton addMonObjetManyToOne ceci:

$monObjetManyToOne->setMonObjetDeBase($this);

Mais ceci ne semble pas être ton cas.