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);
}