Bonjour à tous,

Voila je rencontre un problème avec mon code et je ne parviens pas à le résoudre.
Je suis allé sur différents forums (StackOverflow, OpenClassRoom) ainsi que sur le chat Symfony. Tous me font plus ou moins tourner en bourrique lol, au point ou j'en viens à me persuader que ce que j'essaie de faire est exceptionnel.

Je souhaite simplement avoir deux entités bidirectionnelles liées, l'une (Action) étant nullable car elle regroupe d'autres entités jointes.

Ce que je fais

Voici mon code, que j'ai simplifié pour la compréhension :

Entité User :

class User
{
    /**
     * @var Action
     *
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\Action", inversedBy="userRegister", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    protected $action;

    public function getAction()
    {
        return $this->action;
    }

    public function setAction(Action $action)
    {
        $action->setUserRegister($this);
        $this->action = $action;
    }
}

Entité Action, la relation étant nullable :

class Action
{
    /**
     * @var User
     *
     * @ORM\OneToOne(targetEntity="AppBundle\Entity\User", mappedBy="action")
     * @ORM\JoinColumn(nullable=true)
     */
    protected $userRegister;

    public function getUserRegister()
    {
        return $this->userRegister;
    }

    public function setUserRegister(User $userRegister)
    {
        $this->userRegister = $userRegister;
    }
}

Le controlleur :

    $user = new User();
    $user->setAction(new Action());
    $manager->persist($user);
    $manager->flush();

Mais j'obtiens toujours l'erreur "SQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'action_id' ne peut être vide (null)".

Sur les différents forum, on m'a dit que ce code de toutes façons ne pourrait jamais fonctionner, sans explication ... parfois on m'a dit de persister action() et effectivement ça fonctionne (j'avais déjà essayé) mais quand je demande pourquoi je dois le faire alors qu'il y a un "cascade persist" je n'ai pas de réponse, parfois on me dit de tout mettre à nullable, etc ...

En d'autres termes et vous l'aurez compris je pense, je suis un peu lassé par la multitude de réponses imprécises (dont 90% de fonctionnent) pour un cas qui a mes yeux semblent vraiment "Cas d'école basique", limite "On ne peut pas plus basique avec Doctrine". ^^

Alors si quelqu'un peut m'aider ici ce serait sympatique :)
Merci d'avance

1 réponse


Bonjour Gaylord,

Avant de tenter de te répondre, je voulais préciser que la recherche d'information sur internet, surtout quand on pose une question, il y aura toujours des choses non claire car les gens répondent pour aider, mais ne peuvent (veulent parfois ?) pas perdre trop de temps non plus.

De plus tu trouvera des gens typent "cas d'école basique" qui viennent juste étaler que eux savent tout. Persiste et ne prend pas en compte ce dernier archétype, ils n'avanceront pas.

Après ce petit aparté, en me basant sur la doc de Doctrine : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-one-bidirectional

Il est précisé que par défaut, la requête SQL généré :

CREATE TABLE Cart (
    id INT AUTO_INCREMENT NOT NULL,
    customer_id INT DEFAULT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE Customer (
    id INT AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Cart ADD FOREIGN KEY (customer_id) REFERENCES Customer(id);

On peut voir que la clé étrangère est en DEFAULT NULL. Il est donc naturel de penser que tu peux persister "Cart" sans appliquer la jointure avec un "Customer". Je te recommande donc de supprimer tes deux "nullable=true"