我有一种双向的多对一关系。我们选择Foo
和Bar
。 Foo
有以下内容:
class Foo
{
/**
* @ORM\OneToMany(targetEntity="Bar", mappedBy="foo", cascade={"all"}, orphanRemoval=true)
*/
private $bars;
public function __construct()
{
$this->bars = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* @param mixed $bars
*/
public function setBars($bars)
{
$this->bars = $bars;
}
/**
* @param Bar $bar
*/
public function addBar(Bar $bar)
{
$this->bars->add($bar);
}
/**
* @return mixed
*/
public function getBars()
{
return $this->bars;
}
}
Bar
:
class Bar
{
/**
* @ORM\Id()
* @ORM\ManyToOne(targetEntity="Foo", inversedBy="bars")
* @ORM\JoinColumn(name="foo_id", referencedColumnName="id", nullable=false)
*/
protected $foo;
/**
* @param Foo $foo
*/
public function setFoo(Foo $foo)
{
$this->foo = $foo;
}
/**
* @return Foo
*/
public function getFoo()
{
return $this->foo;
}
}
好的,所以上面的课程,当我写:
$foo = new Foo();
$bar1 = new Bar();
$bar2 = new Bar();
$foo->addBar($bar1);
$foo->addBar($bar2);
并尝试坚持,我得到一个错误,关于每个Bar
的foo属性是如何为空:
同样,如果我把它翻到:
$foo = new Foo();
$bar1 = new Bar();
$bar2 = new Bar();
$bar1->setFoo($foo);
$bar2->setFoo($foo);
我可以坚持,但是我的Foo
新生成的PersistentCollection
属性是空的:
这是预期的行为吗?我已经习惯了不同平台上的其他ORM在分配时连接双向关系,所以我不确定这对于Doctrine / PHP是否正常,或者我的注释是否搞砸了(上面的错误消息让我相信)。
所以,非常感谢任何帮助。
答案 0 :(得分:1)
您需要设置关联的两面,例如
/**
* @param Bar $bar
*/
public function addBar(Bar $bar)
{
if(!$this->bars->contains($bar)) {
$this->bars->add($bar);
$bar->setFoo($this);
}
}
----
/**
* @param Foo $foo
*/
public function setFoo(Foo $foo)
{
if($this->foo !== $foo) {
$this->foo = $foo;
$foo->addBar($this);
}
}
目前你唯一设置协会的一方和Doctrine不会为你做其余的事。
如果您不想修改添加/删除方法,则必须
$bar->setFoo($foo)
$foo->addBar($bar)
每次你想要添加foo或bar
编辑:
如果您只想使用一面进行所有操作,请阅读owning/inverse side。也许它可以帮助解决你的问题。但我不确定它会在您的实体之间建立正确的双向链接。
答案 1 :(得分:1)
您的主要问题是,在添加条形图时,您没有在条形图中设置Foo。
要自动设置您可以执行以下操作(我还添加了一个检查,以查看是否已添加条形图并返回链条集)..
/**
* Add bar
*
* @param Bar $bar
* @return $this
*/
public function addBar(Bar $bar)
{
if (!$this->bars->contains($bar)) {
$this->bars->add($bar);
$bar->setFoo($this)
}
return $this;
}
你可能应该摆脱setBars
,因为我看到如果你使用set但没有使用数组集会导致问题。
另外你应该添加一个删除栏,这样你就不会每次都获取,删除,然后重置,比如..
/**
* Remove bar
*
* @param Bar $bar
* @return $this
*/
public function removeBar(Bar $bar)
{
if ($this->bars->contains($bar)) {
$this->bars->removeElement($bar);
$bar->setFoo(null);
}
return $this;
}
这意味着您的setFoo
需要能够接受空值..
/**
* Set foo
*
* @param Foo $foo
*/
public function setFoo(Foo $foo = null)
{
$this->foo = $foo;
}
答案 2 :(得分:0)
您收到的错误消息告诉您,如果不填写id
字段,就无法保留实体。此外,您的Foo实体中似乎缺少id
字段。
无论如何,id
字段可能已存在于您的数据库中(由Doctrine自动生成),但未设置自动增量,因此在保留之前必须手动填充它。
尝试在您的实体中添加以下代码:
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
希望它有所帮助。
答案 3 :(得分:0)
将此添加到您的addBar
功能中。你错过了后面的参考。从bar
实体到foo
实体
/**
* @param Bar $bar
*/
public function addBar(Bar $bar)
{
$bar->setFoo($this);
$this->bars->add($bar);
}