3

Doctrineの多対多のロジックは私を少し混乱させます。私はレシピとカテゴリーの非常に単純な多対多の関係を持っています。私の基本エンティティクラスも同様に単純です。

レシピエンティティクラス...

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

そして、Categoryエンティティクラス...

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

かなり前向きに見え、Doctrine(およびSymfony2)のドキュメントの例と一致します。Symfonyコンソールアプリを介してこれらのクラスのゲッターとセッターを生成しようとすると、奇妙な動作が発生します。

関係セッター/ゲッターが正しくありません。たとえば、生成されたRecipeクラスのCategoryセッターを例にとってみましょう...

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

    return $this;
}

メソッド名の自動生成がオフになっているようです。これは「addCategory」であり、「category」を渡す必要があります。

これは手動で修正できますが、エンティティジェネレーターを再実行すると、それらが再度追加されます。

私はこれを間違って行っていますか、それともこれはエンティティジェネレータの単なる癖ですか?アノテーションを介してオーバーライドを指定できますか?

4

2 に答える 2

0

それがsymfonyがそれらを生成する方法であるため、あなたは何も悪いことをしていません。私は通常、アプリ/コンソールを使用してそれらを生成しません。現在、それらはうまく機能していないからです。一例は、あなたが言及した単語の複数形について言及したとおりです。もう 1 つの明白な点は、オブジェクトをほぼ PHP 配列として[]扱う表記法を使用しているという事実です。ArrayCollections を配列として扱わないでくださいArrayCollection

これは私が自分で実装した方法です:

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();
于 2013-12-12T00:45:23.013 に答える
0

あなたは何も悪いことをしていません。コレクションプロパティに複数の名前がある場合、Doctrine はメソッドスタブの名前を自動的に単数形にしようとします。これは、コマンド doctrine:generate:entities を実行したときに Doctrine が呼び出す関数です:

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

あなたの場合、Doctrine は単語のカテゴリを「単数化」しようとしますが、単数形を正しく認識できないため、カテゴリを返す末尾から「s」を削除するだけです。

また、ご覧のとおり、Doctrine はメソッド スタブに渡されたパラメーターを単一化せず、$categories一貫性を保つ代わりに$categorie.

これを避けたい場合は、コレクションに複数の単語を使用しないか、複数の単語を使用して後でメソッドを変更します。@keyboardSmasher があなたの投稿にコメントしているように、コマンド doctrine:generate:entities を使用するときに doctrine は既に持っているメソッドを上書きしません。


最後の注意: ArrayCollections配列として使用することはまったく問題ないため、次のコードは正しいです。

$this->categories[] = $category;

ArrayCollectionオブジェクトはCollectionを実装し、それがArrayAccessを実装します。ArrayCollectionsを Arrays として使用できるようにするために、この方法が正確に行われます。

于 2016-03-30T12:35:51.797 に答える