Search code examples
mysqlsymfonydoctrine-ormsymfony-2.8

Symfony / Doctrine: OneToMany insert results in null id


I have two entities that I'm trying to apply a OneToMany / ManyToOne relationship to (one Game has many GameContent).

Game

/**
 * @ORM\OneToMany(targetEntity="GameContent", mappedBy="game")
 */
private $contents;

public function __construct()
{
    $this->contents = new ArrayCollection();
}

public function getContents()
{
    return $this->contents;
}

GameContent

/**
 * @ORM\ManyToOne(targetEntity="Game", inversedBy="contents")
 */
private $game;

And the following code inserts both records into their respective tables:

$game = $form->getData();
$content = new GameContent();
$content->setType('some type');
$game->getContents()->add($content);

$em = $this->getDoctrine()->getManager();
$em->persist($content);
$em->persist($game);
$em->flush();

However, the GameContent's game_id is inserted as null:

INSERT INTO game_content (type, game_id) VALUES (?, ?)
Parameters: { 1: 'some type', 2: null }

I've also tried:

  • changing the order of persist()
  • replacing $game->getContents()->add($content) with $game->addContents($content) by doing $this->contents[] = $content;
  • removing persist($content) and having cascade={"persist"} on the Game entity.

Why is game_id being inserted as null?


My current workaround is:

$em = $this->getDoctrine()->getManager();

$game = $form->getData();
$em->persist($game);

$content = new GameContent();
$content->setType('some type');
$content->setGame($game);
$em->persist($content);

$em->flush();

Solution

  • You have 2 solutions :

    Persist children in controller

    Without cascade={"persist"}

    $em = $this->getDoctrine()->getManager();
    
    // Get data
    $game = $form->getData();
    
    // Create new GameContent and hydrate
    $content = new GameContent();
    $content->setType('some type');
    
    // Associate Game <> GameContent
    $content->setGame($game);
    
    // Persist GameContent
    $em->persist($content);
    
    // Persist Game and commit
    $em->persist($game);
    $em->flush();
    

    Persist children in cascade

    With cascade={"persist"} in OneToMany relation.

    Add in setGame() function, to force association :

    $game->addContent($this);
    

    And remove persist :

    $em = $this->getDoctrine()->getManager();
    
    // Get data
    $game = $form->getData();
    
    // Create new GameContent and hydrate
    $content = new GameContent();
    $content->setType('some type');
    
    // Associate Game <> GameContent
    $content->setGame($game);
    
    // Persist Game and commit
    $em->persist($game);
    $em->flush();
    

    I think the error was also due to the positioning of the persist on game.