簡體   English   中英

在1個Dctrine DQL中合並2個查詢

[英]Merge 2 queries in 1 Doctrine DQL

我正在使用帶有Symfony 2.8的Doctrine 2.4,並且正在嘗試建立一個友誼系統。

我有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中合並這兩個查詢。感謝您的幫助:)

您可以使用LEFT JOINCASE來獲得有效的用戶信息:

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

如果$result為空,則它已經是一個空數組[]

注意:僅針對調用它們的getOneOrNullResultgetSingleResultgetSingleScalarResult方法引發NoResultException異常。

這是使用原則查詢構建器的建議

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

您可以簡單地通過在匹配: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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM