Doctrine2 One-To-Many, самореферентные отношения

В моем объекте «Тема» у меня есть отношение «один ко многим» с самоссылкой $parent:$children.

class Topic
{
    /** @ORM\Id 
    * @Column(type="integer")
    * @ORM\GeneratedValue(strategy="IDENTITY")
    */
    private $id;

    /** @Column(length=40, unique=true) */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="Topic", inversedBy="children")
     */
    private $parent;

    /**
     * @ORM\OneToMany(targetEntity="Topic", mappedBy="parent")
     */
    private $children;
}

Я могу присоединиться к таблице, чтобы получить иерархию родителей и детей следующим образом:

return $this->getEntityManager()->createQuery('
    SELECT t, c FROM My\xxxBundle\Entity\Topic t 
    LEFT JOIN t.children c
    WHERE t.parent IS NULL
')
->getArrayResult();

Вот правильный вывод:

array
  0 => 
    array
      'id' => int 1
      'name' => string 'Parent 1'
      'slug' => string 'p-1'
      'description' => null
      'children' => 
        array
          0 => 
            array
                'id' => int 2
                'name' => string 'Child 1-1'
                'slug' => string 'c-1-1'
                'description' => null
          1 => 
            array
                'id' => int 3
                'name' => string 'Child 1-2'
                'slug' => string 'c-1-2'
                'description' => null
  1 => 
    array
      'id' => int 4
      'name' => string 'Parent 2'
      'slug' => string 'p-2'
      'description' => null
      'children' => 
        array
          empty
...

но если я попытаюсь получить определенные столбцы в инструкции SELECT:

SELECT t.name, c.name FROM My\xxxBundle\Entity\Topic t

Я получаю плоский массив дочерних объектов, то есть только c.name. Если у родителя нет детей, я просто получаю нулевое значение для его имени:

  1 => 
    array (size=1)
      'name' => string 'Child 1-1' (length=14)
  2 => 
    array (size=1)
      'name' => string 'Child 1-2' (length=14)
  3 => 
    array (size=1)
      'name' => null
  4 => 
    array (size=1)
      'name' => string 'Child 3-1' (length=5)

По предложению Марка я переименовал поле имени дочерней сущности:

SELECT t.name, c.name AS child_name FROM My\xxxBundle\Entity\Topic t

но я все еще получаю неправильный формат:

array
  0 => 
    array
      'name' => string 'Parent 1'
      'child_name' => string 'Child 1-1'
  1 => 
    array
      'name' => string 'Parent 1'
      'child_name' => string 'Child 1-2'
  2 => 
    array
      'name' => string 'Parent 2'
      'child_name' => string 'Child 2-1'

person qais    schedule 24.09.2012    source источник


Ответы (1)


Проблема в том, что вы выбираете два поля с одинаковым названием (поле имени из топика и поле имени из дочерних). Эти имена конфликтуют друг с другом при создании ключей массива. Решение этой проблемы заключается в переименовании одного из полей:

SELECT t.name, c.name AS child_name FROM My\xxxBundle\Entity\Topic t

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

Дополнительную информацию см. в документации по DQL: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#select-queries

Изменить Текущий результат, который вы получаете от запроса, логичен. Это соответствует тому, что вы получили бы, если бы запустили эквивалентный SQL-запрос. То, что вы сейчас делаете, это извлечение двух значений из двух таблиц базы данных. Что вам действительно нужно, так это два частичных объекта, отформатированных в виде массива.

Вы можете попробовать использовать Частичные. Это способ в доктрине выбрать только несколько полей объекта. Если вы объедините это с ->getArrayResult(), вы, вероятно, получите правильный результат

return $this->getEntityManager()->createQuery('
    SELECT partial t.{name}, partial c.{name}
    FROM My\xxxBundle\Entity\Topic t 
    LEFT JOIN t.children c
    WHERE t.parent IS NULL
')
->getArrayResult();
person Mark    schedule 24.09.2012
comment
Я все еще получаю неправильный формат массива. Я отредактировал свой вопрос, чтобы добавить дополнительные результаты - person qais; 25.09.2012