2012-11-13 13 views
10

Ich habe ein Problem beim Versuch, QueryBuilder oder DQL verwenden.Verwendung von JOIN in Symfony2/Doctrine SQL

Ich habe die folgende Beziehung:

Benutzer < -1: n-> Profil < -n: m-> RouteGroup < -1: n-> Route

Ich möchte einen DQL machen Das listet alle Routen auf, auf die ein bestimmter Benutzer Zugriff hat. Ich kann diese Informationen mit dem folgenden Code erhalten:

$usr = $this->container->get('security.context')->getToken()->getUser(); 
foreach ($usr->getProfiles() as $profile){ 
    foreach ($profile->getRoutegroups() as $routegroup){ 
     var_dump($routegroup->getRoutes()->toArray()); 
    } 
} 

Aus offensichtlichen Grund, warum ich diesen Code verwenden kann nicht, sonst werde ich meinen Server überlasten, LOL.

ich folgende Ansätze versucht:

DQL:

$em->createQuery('SELECT p FROM CRMCoreBundle:User u 
        JOIN CRMCoreBundle:Profile p 
        JOIN CRMCoreBundle:RoleGroup rg 
        JOIN CRMCoreBundle:Role r 
        WHERE 
        u.id=:user') 
     ->setParameter('user', $user->getId()) 
     ->getResult(); 

Querybuilder (i versucht u.profiles mit - den Namen der Beziehung anstelle des Unternehmens - aber auch nicht funktioniert):

$em->createQueryBuilder() 
     ->select('r') 
     ->from('CRMCoreBundle:User', 'u') 
     ->innerJoin('u.profiles','p') 
     ->where('u.id = :user_id') 
     ->setParameter('user_id', $user->getId()) 
     ->getQuery() 
     ->getResult(); 

Kann jemand bitte helfen ???

UPDATE: Ich Zeljko Lösung versucht und machte dieses Skript:

return $this->getEntityManager() 
     ->createQueryBuilder() 
     ->select('u, r') 
     ->from('CRMCoreBundle:User', 'u') 
     ->innerJoin('u.profiles','p') 
     ->innerJoin('p.routegroups','rg') 
     ->innerJoin('rg.routes','r') 
     ->where('u.id = :user_id')->setParameter('user_id', $user->getId()) 
     ->getQuery() 
     ->getResult(); 

Aber ich habe diesen Fehler:

The parent object of entity result with alias 'r' was not found. The parent alias is 'rg'. 

Wenn i „ändern -> wählen ('u, r')“auf "-> wählen ('r')" ich bekomme diese:

[Semantical Error] line 0, col -1 near 'SELECT r FROM': Error: Cannot select entity through identification variables without choosing at least one root entity alias. 
+1

Um Ihr Update zu beantworten, können Sie nicht nur u und r auswählen. Alles auf dem Weg zu r muss auch ausgewählt werden. also brauchst du wählen ('u, p, rg, r') – intrepion

Antwort

20

Nachdem ich einige Alternativen ausprobiert hatte, fand ich heraus, dass ich eine inverse Suche machen konnte, beginnend mit Routen zu Benutzern. Die Lösung war wie folgt:

+2

Jetzt sollten Sie versuchen, den Unterschied zwischen Links-Join und Inner-Join zu lernen, sie sind sehr unterschiedlich und Innerjoins können Sie Tonnen von Kopfschmerzen sparen. Einfachster Weg; create Category hat viele Relationen von Produkten. Wenn Sie Kategorien abrufen, führen Sie innerJoin von Produkten durch; Sie erhalten nur Kategorien, die tatsächlich Produkte enthalten. Wirklich coole Sache, besonders wenn du es mit "WITH" -Klausel kombinierst. – Zeljko

+0

Kein Problem. Ich kenne bereits den Unterschied zwischen inneren und linken Verbindungen. –

3

In Ihrem DQL, Sie holen den Benutzern bu Sie haben gefragt, wie Sie Routen abrufen können. Was brauchst du eigentlich?

Wie dem auch sei, in RoutesRepository:

$this->createQueryBuilder("r") 
    ->innerJoin("r.Profiles", "p") 
    ->innerJoin("p.User", "u") 
    ->where("u=:user")->setParameter("user", $user) 

Ich verstehe vielleicht nicht die Beziehung, aber ich glaube, Sie dies Ihren Code reflektieren ändern können. Du musst innerJoin verwenden, nicht leftJoin.

+0

Hallo, ich habe deine Lösung versucht aber ein anderes Problem bekommen. Ich habe die obige Frage aktualisiert. Können Sie bitte einen Blick darauf werfen? Danke –

3

Ich bin kein Experte mit Doctrine, aber nur ein sehr ähnliches Problem gelöst. Ich habe mein Problem behoben, indem ich alle Entitäten, die Sie in den Joins im SELECT-Teil der Anweisung verwendet haben.

Ich habe dies nicht getestet, aber das sollte funktionieren.

$em->createQuery('SELECT u, p, rg, r FROM CRMCoreBundle:User u 
       JOIN CRMCoreBundle:Profile p 
       JOIN CRMCoreBundle:RoleGroup rg 
       JOIN CRMCoreBundle:Role r 
       WHERE 
       u.id=:user') 
    ->setParameter('user', $user->getId()) 
    ->getResult(); 

Ich weiß nicht genau warum, aber wenn Sie beinhalten nicht die Einheiten dann der Hydrator weiß nicht, über die Aliase, die Sie für die Entitäten verwenden.

Ich hoffe, dass dies hilft.