5 Stimmen

Doctrine2 One-To-Many, Selbstreferenzierende Beziehung

In meiner 'Topic'-Entität habe ich eine One-to-Many, Self-Referenzierung Beziehung $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;
}

Ich kann die Tabelle verbinden, um die Eltern-Kind-Hierarchie wie folgt zu erhalten:

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

Hier ist die korrekte Ausgabe:

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
...

aber wenn ich spezifische Spalten im SELECT-Statement abrufen möchte:

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

Erhalte ich ein flaches Array von Kind-Entitäten, d.h. nur c.name. Wenn ein Elternteil keine Kinder hat, erhalte ich nur einen Null-Wert für seinen Namen:

  1 => 
    array (size=1)
      'name' => string 'Kind 1-1' (Länge=14)
  2 => 
    array (size=1)
      'name' => string 'Kind 1-2' (Länge=14)
  3 => 
    array (size=1)
      'name' => null
  4 => 
    array (size=1)
      'name' => string 'Kind 3-1' (Länge=5)

Auf Marks Vorschlag hin habe ich das Namensfeld der Kind-Entität umbenannt:

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

aber ich erhalte immer noch das falsche Format:

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

7voto

Mark Punkte 433

Das Problem ist, dass Sie zwei Felder mit demselben Namen auswählen (das Feld name aus dem Thema und das Feld name aus den Kindern). Diese Namen stehen im Konflikt miteinander, wenn die Array-Schlüssel erstellt werden. Die Lösung für dieses Problem besteht darin, eines der Felder umzubenennen:

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

Der Grund, warum Sie ein flaches Array erhalten, liegt darin, dass Sie nicht die Entitäten auswählen, sondern einzelne Werte aus diesen Entitäten.

Weitere Informationen finden Sie in der DQL-Dokumentation: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#select-queries

Bearbeiten Das aktuelle Ergebnis, das Sie aus der Abfrage erhalten, ist logisch. Es entspricht dem, was Sie bekommen würden, wenn Sie die entsprechende SQL-Abfrage ausführen würden. Was Sie derzeit tun, ist das Abrufen von zwei Werten aus zwei Datenbanktabellen. Was Sie wirklich wollen, sind zwei Teilentitäten, die als Array formatiert sind.

Was Sie versuchen können, ist die Verwendung von Teilentitäten. Dies ist eine Möglichkeit in Doctrine, nur wenige Felder einer Entität auszuwählen. Wenn Sie dies mit ->getArrayResult() kombinieren, erhalten Sie wahrscheinlich das richtige Ergebnis

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X