学说2:从自引用实体构建嵌套数组树

时间:2011-06-14 17:37:53

标签: php doctrine-orm

我有一个看起来像这样的实体:

class Privilege
{
/**
 * @Id @Column(type="bigint")
 * @GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @Column(type="string",length=255)
 */
private $name;

/**
 * @Column(type="string",length=255)
 */
private $slug;

/**
 * @OneToMany(targetEntity="Privilege", mappedBy="parent")
 */
private $children;

/**
 * @ManyToOne(targetEntity="Privilege", inversedBy="children")
 * @JoinColumn(name="p_id", referencedColumnName="id")
 */
private $parent;

如果Privilege Entity没有父级,则该字段为NULL。我有一个像这样的基本查询:

    $qb = $this->em->createQueryBuilder()
        ->select('p')
        ->from('\Dashboard\Entity\Privilege', 'p')
        ->andWhere('p.parent IS NULL');

    $q = $qb->getQuery();
    $privileges = $q->getResult();

我希望从这个方法返回的数组结果看起来与此类似:

root1:
    child1:
        subchild1a
        subchild2a
   child2:
        subchild1b
        subchild2b
        subchild3b
            subsubchild1b
   child3:
        subchild1c
root2:
....
....

有没有办法从Doctrine 2中收集结果,以便以这种方式构建数组结果?如果没有,你将如何构建这个数组?我仍在使用Doctrine 2,我注意到$privileges数组中的每个元素都有$privilege->getChildren(),它返回PersistentCollection,显然不是实际记录。

如果我必须自己构建这个嵌套树(即:在Doctrine中没有内置方法来实现它),我如何将此PersistentCollection返回到实际数据中,以便我可以构建某种递归方法为我建造它?我正在浏览文档,但显然是在错误的地方。

2 个答案:

答案 0 :(得分:1)

结果已经在嵌套树中。可以迭代PersistentCollection,就好像它是一个数组:

foreach($parent->getChildren() as $child) {
    // $child is an instance of Privilige
}

仍然应该尝试$privileges = $q->getArrayResult();并查看是否会提供您想要的结果。

答案 1 :(得分:1)

我认为您正在寻找的内容被称为"一对多自我引用的关联"在文档中:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-one-self-referencing

以下是文档中类别层次结构的代码:

<?php
/** @Entity **/
class Category
{
    // ...
    /**
     * @OneToMany(targetEntity="Category", mappedBy="parent")
     **/
    private $children;

    /**
     * @ManyToOne(targetEntity="Category", inversedBy="children")
     * @JoinColumn(name="parent_id", referencedColumnName="id")
     **/
    private $parent;
    // ...

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

&#34;这有效地模拟了类别的层次结构,从数据库的角度来看,这被称为邻接列表方法。&#34;

所以我认为这应该为你完成所有工作,并创建你需要的数组层次结构。

由于您已经在文档中添加了注释,因此您的$parent->getChildren()应该已经包含了所有层次结构,正如@rojoca所说。