Symfony / Doctrine:OneToMany 插入结果为 null id
Symfony / Doctrine: OneToMany insert results in null id
我有两个实体正在尝试应用 OneToMany / ManyToOne 关系(一个游戏有很多游戏内容)。
游戏
/**
* @ORM\OneToMany(targetEntity="GameContent", mappedBy="game")
*/
private $contents;
public function __construct()
{
$this->contents = new ArrayCollection();
}
public function getContents()
{
return $this->contents;
}
游戏内容
/**
* @ORM\ManyToOne(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()
的顺序
- 通过
$this->contents[] = $content;
将 $game->getContents()->add($content)
替换为 $game->addContents($content)
- 删除
persist($content)
并在游戏实体上添加 cascade={"persist"}
。
为什么 game_id
被插入为空值?
我目前的解决方法是:
$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 个解决方案:
在控制器中坚持children
没有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();
坚持children级联
在 OneToMany 关系中与 cascade={"persist"}
。
加入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()
中,所以我在 GameContent::setGame()
中删除了 $game->addContent($this);
。
游戏
/**
* @var ArrayCollection
* @ORM\OneToMany(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;
}
游戏内容
/**
* @ORM\ManyToOne(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:级联关系和保存 "Inverse" 端 )。
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();
请注意,今天(Doctrine 2.7.1),make:entity 实用程序创建了为您做这些事情的方法,在您的情况下,您的游戏实体上会有这样的方法:
public function addContent(GameContent $content): self
{
$this->contents->add($content);
$content->setGame($this); // <-- IMPORTANT PART IS HERE
return $this;
}
然后,在游戏中调用它就可以完成工作了:
this->addContent((new GameContent())->setType('some type'));
我有两个实体正在尝试应用 OneToMany / ManyToOne 关系(一个游戏有很多游戏内容)。
游戏
/**
* @ORM\OneToMany(targetEntity="GameContent", mappedBy="game")
*/
private $contents;
public function __construct()
{
$this->contents = new ArrayCollection();
}
public function getContents()
{
return $this->contents;
}
游戏内容
/**
* @ORM\ManyToOne(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()
的顺序
- 通过
$this->contents[] = $content;
将 - 删除
persist($content)
并在游戏实体上添加cascade={"persist"}
。
$game->getContents()->add($content)
替换为 $game->addContents($content)
为什么 game_id
被插入为空值?
我目前的解决方法是:
$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 个解决方案:
在控制器中坚持children
没有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();
坚持children级联
在 OneToMany 关系中与 cascade={"persist"}
。
加入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()
中,所以我在 GameContent::setGame()
中删除了 $game->addContent($this);
。
游戏
/**
* @var ArrayCollection
* @ORM\OneToMany(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;
}
游戏内容
/**
* @ORM\ManyToOne(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:级联关系和保存 "Inverse" 端 )。
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();
请注意,今天(Doctrine 2.7.1),make:entity 实用程序创建了为您做这些事情的方法,在您的情况下,您的游戏实体上会有这样的方法:
public function addContent(GameContent $content): self
{
$this->contents->add($content);
$content->setGame($this); // <-- IMPORTANT PART IS HERE
return $this;
}
然后,在游戏中调用它就可以完成工作了:
this->addContent((new GameContent())->setType('some type'));