Доктрина 2: построение дерева вложенных массивов из самоподдерживающейся сущности

У меня есть Entity, который выглядит так:

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 возвращать в фактические данные, чтобы я мог построить какой-то рекурсивный метод для его создания для меня? Я просматриваю документы, но, очевидно, не в том месте.

Результаты уже находятся в вложенном дереве. PersistentCollection можно повторить так, как если бы это был массив:

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

Тем не менее вы должны попробовать $privileges = $q->getArrayResult(); и посмотрите, дает ли это результат, который вы предпочтете.

Я думаю, что то, что вы ищете, называется «ассоциация с одиночными именами « один-ко-многим »в документации: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association- mapping.html # один-к-одному-автореферентно

Вот код иерархии категорий из документов:

 <?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(); } } 

«Это эффективно моделирует иерархию категорий и с точки зрения базы данных, называется подходом списка смежности».

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

Поскольку у вас уже есть ваши аннотации, например, в документах, ваш $parent->getChildren() уже должен содержать всю иерархию, как сказал @rojoca.