我有一些使用闭包表模型存储的现有数据。我是 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 的经验几乎为零——希望我在这里没有遗漏任何明显的东西。