2013-03-06 56 views
3

學說的多對多邏輯讓我困惑了一下。我有一個非常簡單的食譜到類別的多對多關係。我的基本實體類同樣簡單。多對多,學說的實體發生器和多元化

的配方實體類...

class Recipe 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="Category", inversedBy="categories") 
    * @ORM\JoinTable(name="recipe_category") 
    **/ 
    private $categories; 

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

    /** 
    * @var string 
    * 
    * @ORM\Column(name="title", type="string", length=255) 
    */ 
    private $title; 


    public function __construct() { 
     $this->categories = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

和類別的實體類...

class Category 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="Recipe") 
    **/ 
    private $recipes; 

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

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=255) 
    */ 
    private $name; 


    public function __construct() { 
     $this->recipes = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

似乎相當兩岸前進和匹配原則(與Symfony2中的)文件的例子。當我嘗試通過Symfony控制檯應用程序爲這些類生成getter和setter時,會出現奇怪的行爲。

關係設置者/獲取者不正確。舉個例子,在生成配方類分類制定者...

/** 
* Add categories 
* 
* @param \Namespace\CookbookBundle\Entity\Category $categories 
* @return Recipe 
*/ 
public function addCategorie(\Namespace\CookbookBundle\Entity\Category $categories) 
{ 
    $this->categories[] = $categories; 

    return $this; 
} 

它看起來像自動生成方法名是關閉的。它應該是「addCategory」,並且應該通過一個「類別」。

雖然我可以手動糾正這個問題,但如果我重新運行實體生成器,它會再次添加它們。

我這樣做是不正確的,或者這只是一個實體生成器的怪癖嗎?我可以通過註釋指定重疊嗎?

+1

那麼看起來很奇怪的是,它既不是'addCategories'或'addCategory',而是'addCategorie' ... – cheesemacfly 2013-03-06 19:31:55

+0

同意。我認爲我可能搞砸了一些註釋,但似乎沒有任何影響,這導致我認爲它比註解/配置問題更像是一個核心問題。 – wlvrn 2013-03-06 19:38:56

+0

我自己遇到了同樣的問題。只需手動修正,然後運行doctrine:generate:實體,只要你想要,它不會替代你現有的方法,拼寫錯誤的方法不會傷害任何東西。 – keyboardSmasher 2013-03-07 00:59:24

回答

0

你沒有做錯任何事,因爲這是symfony如何生成它們。我通常不會使用應用/控制檯來生成它們,因爲目前他們沒有做好工作。正如你所提到的,你已經提到過單詞的複數形式。另一個顯而易見的事實是它使用了[]表示法,它幾乎將ArrayCollection對象視爲一個PHP數組。您不應該將ArrayCollections當作數組處理。

這是多麼我已經實現了它自己:

public function addCategory(Category $category) 
{ 
    if (!$this->categories->contains($category) 
     $this->categories->add($category); 

    return $this; 
} 

,如果它已經添加了不重複添加到陣列中收集。同樣的事情去與刪除:

public function removeCategory(Category $category) 
{ 
    if ($this->categories->contains($category) 
     $this->categories->remove($category); 
} 

我已經遇到很多次是假設你有4類,並添加和刪除它們

$r = new Recipe(); 
$c1 = new Category(); 
$c2 = new Category(); 


$r->addCategory($c1); 
$r->addCategory($c2); 
// at this point $r->getCategories()->toArray()[0] contains $c1 
// and $r->getCategories()->toArray()[1] contains $c2 

$r->removeCategory($c1); 
// now $r->getCategories()->toArray()[0] is empty and 
// $r->getCategories()->toArray()[1] contains $c2 still 
// so in order to get the first category you need to: 

$r->getCategories()->first(); 
+0

我發現「你不應該把ArrayCollections當作數組來處理」。假。 _ArrayCollection_實現_Collection_,它依次實現_ArrayAccess_,以便能夠將ArrayCollections用作數組。同樣在_removeCategory_方法中,您不應該使用_ArrayCollection_對象的_remove_。 _remove_方法需要一個鍵,而不是一個元素。如果你想刪除一個元素,你應該使用_removeElement_方法。在刪除之前,_remove_和_removeElement_都檢查現有的鍵/元素,因此您也不需要檢查_removeCategory_內部。 – Kyopaxa 2016-03-30 12:01:48

0

你沒有做錯什麼。只是當一個集合屬性有複數名稱時,Doctrine會自動嘗試將方法存根的名稱單數化。這是當你運行命令教條學說調用該函數:生成:實體:

$methodName = Inflector::singularize($methodName); 

在你的情況,學說試圖「singularize」字類別但未能正確識別的單數形式,所以它只是從結尾刪除's'返回分類

另外,正如您看到的,Doctrine不會將傳遞給方法存根的參數單數化,而是將$categories而不是一致並將其修改爲$categorie

如果您想避免這種情況,您不要使用複數單詞作爲集合,或者使用複數單詞並在之後改變方法。由於@keyboardSmasher對你的帖子發表評論,所以在使用doctrine命令時,doctrine不會覆蓋你已經擁有的方法:generate:entities,如果單獨放在那裏,錯誤的方法不會傷害太多。


最後需要說明的:使用ArrayCollections陣列是完全沒有問題,所以該代碼是正確的:

$this->categories[] = $category; 

的ArrayCollection對象實現收集,這又實現ArrayAccess。這樣做正是爲了能夠使用ArrayCollections作爲數組。