簡體   English   中英

使用閉包表模型與Doctrine2進行分層數據

[英]Hierarchal data with Doctrine2 using closure table model

我使用閉包表模型存儲了一些現有數據。 我是Doctrine的新手,並試圖以“Doctrine方式”實現一個Entity,並且不確定如何繼續。 我想要遵循的原則是實體應該只是一個普通的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 / $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實現的東西嗎? 如果沒有,有沒有更好的方法來解決這個問題?

如果這看起來像是一種合理的方法,我想知道怎么去攻擊這個? 我正在尋找我需要放置這些文件的位置/我需要如何設置類與有人給我實際實現。 任何有助於我入門的文檔或示例都將非常感激。 我對Doctrine的經驗非常少 - 希望我在這里不會錯過任何明顯的東西。

我想如果你想構建一個分層數據庫,你應該尋找教義ODM項目。 您想要的所有內容都內置於其中,您可以自定義節點。

有一個mongoDB適配器,你也可以看看DoctrinePHPCR項目,它有幾個數據庫的適配器。

即使您想使用doctrine ORM實現自己的方法,您也可以查看它們的實現,以了解它們的工作原理。 它們具有基於節點的關系,因此您始終可以引用對象中樹中的相鄰節點。

希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM