2014-07-22 55 views
1

我有一個雙向的多對一關係。我們來用FooBarFoo有以下幾點:Doctrine 2 ArrayCollections - 我錯過了什麼?

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屬性如何爲空:

enter image description here

同樣,如果我周圍扳起:

$foo = new Foo(); 

$bar1 = new Bar(); 
$bar2 = new Bar(); 

$bar1->setFoo($foo); 
$bar2->setFoo($foo); 

我能堅持,但後來我Foo新近產生PersistentCollection該屬性是空的:

enter image description here

這是有意的行爲?我習慣了不同平臺上的其他ORM在分配時接合雙向關係,所以我不確定這對於Doctrine/PHP是否正常,或者我的註釋混亂了(上面的錯誤消息讓我相信)。

所以,任何幫助將不勝感激。

+0

你試圖堅持美孚你打電話之前setFoo? – Alex

+0

沒有變化。 'PersistentCollection'仍爲空 –

回答

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

目前你唯一的設定關聯的一側,學說不爲你做休息。

如果你不希望修改添加要添加一個富或酒吧

修改/刪除你的方法來

$bar->setFoo($foo) 
$foo->addBar($bar) 

每次:

如果你想只能使用一面做所有的操作,閱讀有關owning/inverse side。也許它可以幫助你解決問題。但我不確定它會在您的實體之間做正確的bidir鏈接。

+0

我認爲我走在正確的軌道上。 'Bar'實際上是'Foo'和'Baz'之間的多對多關係的關聯表,它包含一些元數據。現在,它給我一個關於Bar'沒有自己身份的錯誤。它包含'Foo'和'Baz'的外鍵,但沒有自己的ID。我不確定是否應該給它一個自己增加的自己的ID,或者如果我可以讓它識別外部ID組合作爲它自己的身份。對不起,我之前沒有提到它。我在NDA下經營。 –

+0

看看[這個](http://docs.doctrine-project.org/en/latest/tutorials/composite-primary-keys.html),@ KevinM1。它有幫助嗎? – AlixB

+0

不幸的是,錯誤依然存在。錯誤消息是:Bar​​類型的實體通過外部實體Foo具有身份,但是該實體本身沒有身份。您必須在相關實體上調用EntityManager#persist(),並確保在試圖保留「Bar」之前生成了一個標識符。如果生成後插入ID(例如MySQL自動遞增或PostgreSQL SERIAL),這意味着您必須在兩個持久操作之間調用EntityManager#flush()。 –

1

你的主要問題是,當你添加一個Bar時,你並沒有在Bar中設置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; 
} 
0

你正在告訴一個實體不能沒有填充被持久化的錯誤信息id字段。此外,它看起來像你在你的Foo實體中缺少id字段。

無論如何,id字段可能已經存在於您的數據庫中(由Doctrine自動生成),但未設置自動增量,因此在保留前必須手動填寫。

嘗試在實體加入以下代碼:

/** 
* @var integer 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

希望它能幫助。

+0

@Id定義在'protected $ foo;'的上面,它是一個有效的解決方案。 – AlixB

+0

默認使用''auto''策略,並且''@ORM \ Id()''是有效的 – ins0

0

將此添加到您的addBar函數。你錯過了後衛。從bar實體到foo實體

/** 
* @param Bar $bar 
*/ 
public function addBar(Bar $bar) 
{ 
    $bar->setFoo($this); 
    $this->bars->add($bar); 
}