2015-06-05 3 views
3

У меня есть некоторые существующие данные, хранящиеся с использованием closure table model. Я новичок в Doctrine и пытаюсь реализовать Entity для этого «Doctrine way» и не совсем уверен, как действовать. Философия, которой я пытаюсь следовать, заключается в том, что Entity должен быть просто старым PHP-объектом и что для настройки ассоциаций родитель-ребенок следует использовать некоторую аннотацию.Иерархические данные с Doctrine2 с использованием таблицы закрытия таблицы

В этом посте я буду использовать Категория в качестве примера. Вот что я себе лицо выглядит как:

<?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/$children заселенными, когда я принесу из хранилища и когда $em->flush() называется, есть SQL выполняется с учетом недавно добавленными детьми.

Некоторых примеров 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? Если нет, есть ли лучший способ приблизиться к этому?

Если это действительно разумный подход, мне интересно, как это сделать? Я больше ищу, где мне нужно поставить эти файлы/как мне нужно настроить классы, а кто-то дает мне реальную реализацию. Любая документация или примеры, которые помогут мне начать работу, будут высоко оценены. У меня почти нулевой опыт работы с Доктриной - надеюсь, я не пропущу ничего очевидного здесь.

ответ

0

Я думаю, что если вы хотите построить иерархическую базу данных, вам следует искать проект ODM доктрины. Все, что вам нужно, встроено в это, и вы можете настроить свой узел.

Имеется адаптер mongoDB, а также вы можете посмотреть проект DoctrinePHPCR, в котором есть адаптеры для нескольких баз данных.

Даже если вы хотите реализовать свой собственный подход с использованием доктрины ORM, вы можете посмотреть на их реализации, чтобы получить представление о том, как они работают. Они имеют отношения на основе узлов, поэтому вы всегда имеете ссылку на соседние узлы в дереве вашего объекта.

Надеюсь, что это поможет.

Смежные вопросы