2017-12-15 1 views
0

Ich bin ziemlich neu in Symfony und Doctrine und ich kann keine Lösung für mein Problem finden.Symfony/Doctrine: Wählen Sie mehrere Tabellen

Ich habe eine Datenbanktabelle transactional und eine customer genannt. In der Tabelle transactional befindet sich ein Fremdschlüssel für die Tabelle customer. Jetzt möchte ich alle Daten von beiden Tabellen bekommen. Aber die Kundenfelder sind alle auf null gesetzt. Hier

ist der Fremdschlüssel in der transactional PHP Objekt:

transactional:

/** 
* @var \AppBundle\Entity\Customer 
* 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Customer") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="fk_customer", referencedColumnName="id") 
* }) 
*/ 
private $fkCustomer; 

Die Lehre Abfrage:

$em = $this->getDoctrine()->getManager(); 
$transactions = $em->getRepository('AppBundle:Transactional')->findAll(); 
dump($transactions); 

Das Ergebnis:

0 => Transactional {#483 ▼ 
-id: 1 
-date: DateTime @1510873200 {#493 ▶} 
-fkCustomer: Customer {#566 ▼ 
    +__isInitialized__: false 
    -id: 1 
    -gender: null 
    -firstname: null 

Vielen Dank für Ihre Zeit und Hilfe. =)

Antwort

1

Das ist lazy loading lehre.

Sobald Sie auf die Kundeneigenschaft Ihres Transactional-Objekts zugreifen, werden die zugehörigen Informationen geladen.

Dies ist jedoch nicht ideal, wenn Sie über viele Transaktionseinträge iterieren, da jedes Kundenobjekt über eine einzige Abfrage geladen wird.

Sie können dieses Problem lösen, indem entweder die fetchMode zu EAGER Einstellung wie:

/** 
* @var \AppBundle\Entity\Customer 
* 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Customer", fetch="EAGER") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="fk_customer", referencedColumnName="id") 
* }) 
*/ 
private $fkCustomer; 

, die die Kundendaten vollständig anstelle der Verwendung eines Proxy-Objekt füllen sollte.

Eine andere Möglichkeit wäre das Laden der Transaktionselemente über eine benutzerdefinierte Repository-Methode, die explizit die Kundendaten verbindet. Zum Beispiel durch ein eigenes Repository für Transactional Schaffung und Erhaltung einer funciton wie folgt hinzu: https://symfony.com/doc/3.3/doctrine/repository.html

+0

Danke, ich habe die erste Option bisher versucht, aber es hat nicht geklappt. Aber ich lese jetzt in den zweiten. – Dario

+0

Hey, ich habe die zweite Lösung noch nicht ausprobiert, bin aber auf etwas gestoßen. Im Symfony-Debugging-Tool habe ich folgende Abfrage gefunden: SELECT t0.id AS id_1, t0.date AS date_2, t0.fk_customer AS fk_customer_3 FROM transactional t0. Sollte es keine Join-Anweisung geben? Oder wird die Join-Anweisung durch die Doktrin behandelt? – Dario

+0

Nein, wenn Sie die Standard-Repository-Funktionen wie findAll-Doktrin verwenden, wird nur die Tabelle für diese Klasse abgefragt.Wenn EAGER funktioniert, sollte es ihnen ja beitreten, aber ich habe auch Fälle, in denen der EAGER so gut wie nichts tut. Ich benutze immer benutzerdefinierte Repositories in diesen Fällen, weil ich die Abfrage definieren kann, die verwendet werden sollte, und durch den manuellen Join tatsächlich eine einzige Datenbankabfrage anstelle von vielen erreichen – Joe

1

Sie setzen müssen Typ eifrig holen:

public function load() 
{ 
    $qb = $this->_em->createQueryBuilder(); 
    $qb->select('t, c') 
     ->from('AppBundle:Transactional','t') 
     ->join('t.fkCustomer', 'c'); 

    return $qb->getQuery()->execute(); 
} 

, wie eine benutzerdefinierte Repository anlegen in der Dokumentation gefunden werden :

Eager Typ: Laden Sie die zugehörige Entität ebenfalls.

Lazy Typ: Laden Sie die zugehörige Entität nach Bedarf.

/** 
* @var \AppBundle\Entity\Customer 
* 
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Customer",fetch="EAGER") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="fk_customer", referencedColumnName="id") 
* }) 
*/ 
private $fkCustomer;