2012-11-13 10 views
10

QueryBuilderまたはDQLの使用中に問題が発生しました。Symfony2/Doctrine SQLでJOINを使用する

私は次のような関係があります。私はDQLをしたいと思いN->ルート

ユーザー< -1:N->プロフィール< -n:M->するRouteGroup < -1を特定のユーザーがアクセスするすべてのルートを一覧表示します。 私は、次のコードで、この情報を得ることができます。私はこのコードを使用傾ける明白な理由のために

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

、そうでない場合、私は私のサーバーが過負荷になり、LOL。

私は、次のアプローチを試してみました:

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(私はu.profilesを使用してみました - 代わりに、実体の関係の名前を - しかし、これも動作しませんでした)。

誰かがお手伝いできますか?

UPDATE:私はゼリコのソリューションを試してみましたが、このスクリプトを作っ:

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

をしかし、私はこのエラーを得た:私は、「変更した場合は

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

を - >選択します( 'U、R'

あなたのDQLで
[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

あなたのアップデートに答えるには、uとrを選択するだけではいけません。rへの道に沿ってすべてが選択されなければなりません。あなたはselect( 'u、p、rg、r')が必要です – intrepion

答えて

20

いくつかの選択肢を試した後、私はルートからユーザーに向かって逆ルックアップを行うことができることを知りました。その解決策は以下の通りです:

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

今左の結合と内部の結合の違いを学ばなければならない、彼らは非常に異なっていて、内部結合は頭痛のトンを救うことができます。最も簡単な方法。 create categoryには多くのProducts関係があります。カテゴリを取得するときは、製品のinnerJoinを実行します。あなたはそれに実際に製品を持っているカテゴリーだけを得るでしょう。本当にクールなこと、特にあなたが "WITH"節と組み合わせるとき。 – Zeljko

+0

問題ありません。私はすでにインナーとレフトのジョインの違いを知っています。 –

3

、あなたがフェッチされているユーザー府: - )」する ">( 'R')を選択し、" 私はこれを取得します経路を取得する方法を尋ねられました。実際に何が必要ですか? RoutesRepositoryでとにかく

、:

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

私は関係を理解し​​ていない可能性がありますが、私はあなたのコードを反映するために、これを変更することができると思います。 leftJoinではなくinnerJoinを使用する必要があります。

+0

こんにちは、私はあなたの解決策を試みましたが、別の問題がありました。上記の質問を更新しました。どうぞご覧ください。ありがとう –

3

私はDoctrineの専門家ではありませんが、非常によく似た問題を解決しました。ステートメントのSELECT部分​​で、結合で使用していたすべてのエンティティを含めることで、問題を解決しました。

これはテストしていませんが、これはうまくいくはずです。

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

私は理由を正確に知りませんが、あなたはエンティティを含んでいないならば、ハイドレーターを使用すると、エンティティのために使用されている別名を認識していません。

私はこれが助けてくれることを願っています。