3

クロージャ テーブル モデルを使用して保存された既存のデータがいくつかあります。私はDoctrineを初めて使用し、この「Doctrineの方法」でエンティティを実装しようとしていますが、どうすればよいかわかりません。私が従おうとしている哲学は、エンティティは単純な古い PHP オブジェクトであるべきであり、親子の関連付けを構成するために何らかの注釈を使用する必要があるということです。

この投稿では、Category をエンティティの例として使用します。エンティティが次のように見えると私が想像するものは次のとおりです。

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Table(name="categories)
 * @ORM\Entity
 */
class Category
{
    /**
     * @ORM\Column(name="categoryID", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $categoryID;

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

    /**
     * @MyORM\TreeParent(targetEntity="Category", closureTable="categories_paths", ancestorColumn="ancestorID", descendantColumn="descendantID")
     */
    protected $parent;

    /**
     * @MyORM\TreeChildren(targetEntity="Category", closureTable="categories_paths", ancestorColumn="ancestorID", descendantColumn="descendantID")
     */
    protected $children;

    public function __construct()
    {
        $this->children = new ArrayCollection();
    }

    public function getChildren()
    {
        return $this->children;
    }

    public function addChild(Category $child)
    {
        $this->children[] = $children;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function setParent(Category $parent)
    {
        $this->parent = $parent;
    }
}

閉鎖テーブルは次のようになります。

categories_paths(ancestorID, descendantID, pathLength)

このテーブルは基本的には結合テーブルです。親子関係のみが格納されるため、多対多の関係を作成するときにエンティティが存在しないのと同様に、ここにエンティティが存在しても意味がないと思います。と@JoinTable

他のエンティティと同じようにカテゴリ エンティティを使用できるようにしたいと考えています。リポジトリから取得したときに$parent/が入力され、呼び出されたときに SQL が実行され、新しく追加された子が反映されます。$children$em->flush()

ここで使用される SQL の例:

新しい子を追加します。

INSERT INTO categories_paths (ancestorID, descendantID, pathLength)
SELECT a.ancestorID, d.descendantID, a.pathLength+d.pathLength+1
FROM categories_paths a, categories_paths d
WHERE a.descendantID = $parentCategoryID AND d.ancestorID = $childCategoryID

サブツリーを新しい親に移動します。

// Delete all paths that end at $child
DELETE a FROM categories_paths a
JOIN categories_paths d ON a.descendantID=d.descendantID
LEFT JOIN categories_paths x
ON x.ancestorID=d.ancestorID AND x.descendantID=a.ancestorID
WHERE d.ancestorID = $subtreeCategoryID and x.ancestorID IS NULL

// Add new paths
INSERT INTO categories_paths (ancestorID, descendantID, pathLength)
SELECT parent.ancestorID, subtree.descendantID,
       parent.pathLength+subtree.pathLength+1
FROM categories_paths parent
JOIN categories_paths subtree
WHERE subtree.ancestorID = $subtreeCategoryID
  AND parent.descendantID = $parentCategoryID;

カテゴリのすべての子を取得します。

SELECT * FROM categories
JOIN categories_paths cp ON cp.descendantID=categories.categoryID
WHERE cp.ancestorID = $catogeryID
AND cp.depth=1

ここでいくつか質問があります。まず第一に、これは合理的なアプローチ/Doctrineで実装できるもののように見えますか? そうでない場合、これにアプローチするより良い方法はありますか?

これが合理的なアプローチのように思える場合、これを攻撃する方法を考えていますか? これらのファイルを配置する必要がある場所/クラスを設定する方法と、実際の実装を提供してくれる人をもっと探しています。始めるのに役立つドキュメントや例は大歓迎です。私は Doctrine の経験がほとんどありません。

4

1 に答える 1

0

階層データベースを構築したい場合は、doctrine ODM プロジェクトを探すべきだと思います。必要なものはすべてそこに組み込まれており、ノードをカスタマイズできます。

mongoDB アダプターがあり、複数のデータベース用のアダプターを備えた DoctrinePHPCR プロジェクトも参照できます。

ドクトリン ORM を使用して独自のアプローチを実装したい場合でも、それらの実装を見て、それらがどのように機能するかを理解することができます。それらにはノードベースの関係があるため、オブジェクトのツリー内の隣接するノードを常に参照できます。

それが役立つことを願っています。

于 2015-06-05T19:29:29.900 に答える