2016-09-07 6 views
2

私はSymfony 2.8でDoctrine 2.4を使用しています。私は友情システムを構築しようとしています。1 Doctrine DQLで2つのクエリをマージする

私は私のMateRelationshipエンティティを持っている:

class MateRelationship 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(type="integer", name="id") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User") 
    * @ORM\JoinColumn(name="sender", referencedColumnName="id", nullable=false) 
    * 
    */ 
    private $sender; 

    /** 
    * @ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User") 
    * @ORM\JoinColumn(name="receiver", referencedColumnName="id", nullable=false) 
    * 
    */ 
    private $receiver; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(type="datetime", nullable=false) 
    */ 
    private $date; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(type="boolean", nullable=false) 
    */ 
    private $invitationAccepted; 

私の目標は、与えられたユーザ(利用者が送信者または受信者である場合にかかわらず)のためのすべての受け入れの友人関係を取得するためにDQLクエリを作ることです。

私は2つのクエリで結果をマージすることができましたが、最適化されておらず、$limitをこのように実装するのは難しいです。

public function getMates($user, $limit = 0){ 

    $query1 = $this->_em->createQuery('SELECT m, u.nickname, u.username FROM AcmeUserBundle:MateRelationship m JOIN m.receiver u WHERE m.invitationAccepted = 1 AND m.sender = :user') 
      ->setParameter('user', $user); 

    try{ 
     $result1 = $query1->getResult(); 
    } 
    catch(\Doctrine\ORM\NoResultException $e){ 
     $result1 = []; 
    } 

    $query2 = $this->_em->createQuery('SELECT m, u.nickname, u.username FROM AcmeUserBundle:MateRelationship m JOIN m.sender u WHERE m.invitationAccepted = 1 AND m.receiver = :user') 
      ->setParameter('user', $user); 

    try{ 
     $result2 = $query2->getResult(); 
    } 
    catch(\Doctrine\ORM\NoResultException $e){ 
     $result2 = []; 
    } 

    return array_merge($result1, $result2); 
} 

私は->setMaxResults($limit)を使用できるように、単一のクエリを持っているしたいのですが、私はあなたが簡単に行うことができますどのようにあなたの助けのための1 のおかげでこれらの2つのクエリをマージする:)

答えて

1

ここでは、 `` usen.`または `urec`の別名でu.`を変更する必要が教義クエリビルダ

public function getMates($user, $limit = 0) 
{ 
    // Create query builder 
    $queryBuilder = $this->_em->getRepository("AcmeUserBundle:MateRelationship")->createQueryBuilder('m'); 

    // Create 'or' expression 
    $or = $queryBuilder->expr()->orX(); 
    $or 
     ->add('m.sender = :user') 
     ->add('m.receiver = :user'); 

    // Create the query 
    $queryBuilder 
     ->andWhere('m.invitationAccepted = 1') 
     ->andWhere($or) 
     ->setMaxResults($limit) 
     ->setParameter('user', $user); 

    // Return the result 
    return $queryBuilder->getQuery()->getResult(); 
} 
-2

見当がつかない:userと一致するときはORと入力してください。これはreceiverまたはsenderのいずれかになります。

SELECT m, usen.nickname, usen.username, urec.nickname, urec.username 
FROM AcmeUserBundle:MateRelationship m 
JOIN m.sender usen 
JOIN m.receiver urec 
WHERE m.invitationAccepted = 1 AND 
(m.receiver = :user OR m.sender= :user) 
+0

を使用しての提案です。 – yceruto

+1

しかしそれほど単純ではないと思います。 'usen.nickname'と' m.sender <>:user'を使うとどうなりますか? – yceruto

+0

この場合、 'JOIN'の代わりに' LEFT JOIN'を使う必要があります。そうでないと 'sender'と' receiver'の両方が ':user'と同じになります。 – yceruto

1

あなたは、有効なユーザー情報を取得するためにLEFT JOINCASEを使用してこれを行うことができます。$resultが空である

public function getMates($user, $limit = 0) 
    { 
     $dql = <<<DQL 
      SELECT 
       m, 
       CASE usen.nickname IS NULL WHEN TRUE THEN urec.nickname ELSE usen.nickname END AS nickname, 
       CASE usen.username IS NULL WHEN TRUE THEN urec.username ELSE usen.username END AS username, 
       CASE usen.nickname IS NULL WHEN TRUE THEN 'sender' ELSE 'receiver' END AS relationship 
      FROM AcmeUserBundle:MateRelationship m 
      LEFT JOIN m.sender usen 
      LEFT JOIN m.receiver urec 
      WHERE m.invitationAccepted = 1 AND (m.receiver = :user OR m.sender= :user) 
DQL; 

     return $this->_em->createQuery($dql) 
      ->setParameter('user', $user) 
      ->setMaxResults($limit) 
      ->getResult(); 
    } 

場合、それはすでに空の配列[]です。

注:NoResultException例外は彼らだけが呼び出されgetOneOrNullResultgetSingleResultまたはgetSingleScalarResult方法のためにスローされます。

+1

CASE文のエイリアスを使用して回答を更新しました。データを抽出するのが少し楽です。 – yceruto

+0

Doctrineは例外をスローします。 Doctrine \ ORM \ Query \ QueryException "" [構文エラー]行0、列32:エラー:予期しない 'NULL'問題](https://github.com/doctrine/doctrine2/issues/3160)? – Kaz

関連する問題