我使用closure table model存储了一些现有数据。我是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
/ $children
并且$em->flush()
是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
调用,执行SQL以反映新添加的子项。
此处使用的SQL的一些示例:
添加一个新孩子:
location.reload();
将子树移动到新父级:
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
location.reload();
});
获取所有类别的孩子:
{{1}}
我在这里有几个问题。首先,这似乎是一种合理的方法/可以用Doctrine实现的东西吗?如果没有,是否有更好的方法来解决这个问题?
如果这看起来像是一种合理的方法,我想知道怎么去攻击这个?我正在寻找我需要放置这些文件的位置/我需要如何设置类而不是某人给我实际实现。任何有助于我入门的文档或示例都将非常感激。我对Doctrine的经验非常少 - 希望我不会错过任何明显的东西。
答案 0 :(得分:0)
我认为如果你想建立一个分层数据库,你应该寻找教义ODM项目。您想要的所有内容都内置于其中,您可以自定义节点。
有一个mongoDB适配器,你也可以看看DoctrinePHPCR项目,它有多个数据库的适配器。
即使您想使用doctrine ORM实现自己的方法,您也可以查看它们的实现,以了解它们的工作原理。它们具有基于节点的关系,因此您始终可以引用对象树中的相邻节点。
希望有所帮助。