Symfony / Doctrine:OneToMany插入导致null id

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Symfony / Doctrine:OneToMany插入导致null id相关的知识,希望对你有一定的参考价值。

我有两个实体,我正在尝试应用OneToMany / ManyToOne关系(一个游戏有很多GameContent)。

游戏

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

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

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

GameContent

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

以下代码将两个记录都插入到各自的表中:

$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();

但是,GameContent的game_id作为null插入:

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

我也尝试过:

  • 改变persist()的顺序
  • $game->getContents()->add($content)$game->addContents($content)取代$this->contents[] = $content;
  • 删除persist($content)并在游戏实体上使用cascade={"persist"}

为什么game_id被插入为null?


我目前的解决方法是:

$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();
答案

你有2个解决方案:

把孩子留在控制器里

没有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();

坚持级联的孩子

cascade={"persist"}在OneToMany关系。

添加setGame()函数,强制关联:

$game->addContent($this);

并删除持久性:

$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();

我认为错误也是由于持久性在游戏中的定位。

另一答案

除了接受的答案之外,我的下一步是创建一个表单来处理GameContent数据,这导致了进一步的更改和一些简化的逻辑。

我现在在setGame() Game::addContent(),所以我在$game->addContent($this);删除了GameContent::setGame()

游戏

/**
 * @var ArrayCollection
 * @ORMOneToMany(targetEntity="GameContent", mappedBy="game", cascade={"persist"})
 */
private $contents;

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

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

public function addContent(GameContent $content)
{
    $this->contents->add($content);
    $content->setGame($this);

    return $this;
}

public function removeContent(GameContent $content)
{
    $this->contents->removeElement($content);

    return $this;
}

GameContent

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

public function setGame(Game $game)
{
    $this->game = $game;

    return $this;
}

/**
 * @return Game
 */
public function getGame()
{
    return $this->game;
}

真实的表单处理逻辑将如下所示:

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

更多信息请访问:http://symfony.com/doc/2.8/form/form_collections.html(参见Doctrine:级联关系并保存“反向”方面)。

以上是关于Symfony / Doctrine:OneToMany插入导致null id的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 和 Doctrine 使迁移无效

如何在 Symfony 2 / Doctrine 中启用 ENUM

Doctrine 2,Symfony 2 中的独特约束

Symfony - Doctrine 实体的返回类型

Symfony 2 Doctrine 导出到 JSON

[Symfony][Doctrine]文件映射驱动程序必须有一个有效的目录路径