Php 条令2阵列集合-我遗漏了什么吗?
我有双向多对一关系。让我们使用Php 条令2阵列集合-我遗漏了什么吗?,php,symfony,doctrine-orm,Php,Symfony,Doctrine Orm,我有双向多对一关系。让我们使用Foo和BarFoo具有以下功能: class Foo { /** * @ORM\OneToMany(targetEntity="Bar", mappedBy="foo", cascade={"all"}, orphanRemoval=true) */ private $bars; public function __construct() { $this->bars = new \Doct
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;
}
}
和条
:
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);
我可以持久化,但是我为该属性新生成的PersistentCollection
为空:
这是故意的行为吗?我习惯于不同平台上的其他ORM在分配时连接双向关系,因此我不确定这对于Doctrine/PHP是否正常,或者我的注释是否混乱(上面的错误消息让我相信这一点)
因此,任何帮助都将不胜感激。例如,您需要设置关联的双方
/**
* @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);
}
}
目前,你只设定了协会和教义的一个方面,其余的都不适合你
如果不想修改添加/删除方法,则必须
$bar->setFoo($foo)
$foo->addBar($bar)
每次你想添加一个foo或bar
编辑:
如果只想使用一面来执行所有操作,请阅读。也许这能帮你解决问题。但我不确定它是否能在您的实体之间建立正确的bidir链接。您的主要问题是,在添加条形图时,您没有在条形图中设置Foo 要自动设置,您可以执行以下操作(我还添加了一个检查,查看是否已经添加了条,并返回到链集) 您可能应该去掉
设置
,因为我可以看到,如果使用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;
}
您收到的错误消息告诉您,如果不填写
id
字段,实体将无法持久化。此外,您的Foo实体中似乎缺少id
字段
无论如何,id
字段可能已经在您的数据库中(由条令自动生成),但是没有设置自动增量,因此在持久化之前必须手动填充它
尝试在实体中添加以下代码:
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
希望有帮助。将其添加到您的
addBar
功能中。您错过了从bar
实体到foo
实体的后参考
/**
* @param Bar $bar
*/
public function addBar(Bar $bar)
{
$bar->setFoo($this);
$this->bars->add($bar);
}
在调用setFoo之前,您是否尝试保持Foo?没有更改
PersistentCollection
仍为空@Id在受保护的$foo上方定义
是一个有效的解决方案。默认情况下,条令使用自动
策略,并且@ORM\Id()
是有效的。我认为我的思路是正确的Bar
实际上是Foo
和Baz
的多对多关系之间的关联表,其中包含一些元数据。现在,它给了我一个错误,关于Bar
如何没有自己的标识。它包含Foo
和Baz
的外键,但没有自己的ID。我不确定是否应该给它自己一个自动递增的ID,或者我是否可以让它将外键ID组合识别为自己的标识。对不起,我以前没提过。我是在保密协议下运作的。看看,@KevinM1。这有用吗?不幸的是,错误仍然存在。错误消息是:Bar类型的实体通过外部实体Foo具有标识,但该实体本身没有标识。您必须对相关实体调用EntityManager#persist(),并确保在尝试持久化“Bar”之前生成了标识符。在生成插入后ID(如MySQL自动增量或PostgreSQL串行)的情况下,这意味着您必须在两个持久化操作之间调用EntityManager#flush()。错误是明确的。你必须做newfoo;坚持齐平代码>然后添加一些条。如果教条这么说,我认为没有任何解决办法。或者,你可以添加一个与Foo或Baz无关的id,就是这样。谢谢你的帮助!
/**
* @param Bar $bar
*/
public function addBar(Bar $bar)
{
$bar->setFoo($this);
$this->bars->add($bar);
}