2016-02-02 69 views
3

正如標題狀態,的Symfony /原則關係COUNT在實體

我想運行1個查詢從表中得到的結果與它們各自的關係的計數。

可以說我有一個Person實體與一個Friend實體

Person實體可能看起來像下面這樣的一對多關係:

class Person 
{ 
    /** 
    * @ORM\OneToMany(...) 
    */ 
    protected $friends; 

    public function __construct() 
    { 
     $this->friends = new ArrayCollection(); 
    } 

    ... 
} 

一個經典的SQL解決方案,我想要什麼實現可能看起來像下面這樣:

SELECT p.*, COUNT(f.id) as friendsCount 
FROM Persons p 
LEFT JOIN Friends f 
ON f.person_id = p.id 
GROUP BY p.id 

現在我想知道,如果這可以在DQL完成以及和存儲值到Person實體

可以說我擴大Person實體,如:(請記住,這只是一個想法)

class Person 
{ 
    /** 
    * @ORM\OneToMany(...) 
    */ 
    protected $friends; 

    protected $friendsCount; 

    public method __construct() 
    { 
     $this->friends = new ArrayCollection(); 
    } 

    ... 

    public function getFriendsCount() 
    { 
     return $this->friendsCount; 
    } 
} 

現在我無法找到我怎麼可能從DQL實體填充計數值:

SELECT p, /* What comes here ? */ 
FROM AppBundle\Entity\Person p 
LEFT JOIN p.friends f 
GROUP BY p.id 

PS:我不硝酸鉀我可以這樣做:

$person->getFriends()->count(); 

甚至標記爲額外的懶得到計數結果。

我只是雖然這計數關係示例很好地證明了我正在嘗試做什麼。

(這是填充實體從DQL非@ORM\Column屬性)

這是可能的教義?

這是否打破了一些堅實的原則? (SRP?)

曲奇爲您思緒之中;)

回答

4

你可能只是想選擇計數,你需要它,如上面所描述$person->getFriends()->count();。但是,您可以同時選擇一個對象,並在同一時間的計數 - 看到這些Doctrine DQL example S,有一個非常相似,你在做什麼:

SELECT p, COUNT(p.friends) 
FROM AppBundle\Entity\Person p 
LEFT JOIN p.friends f 
GROUP BY p.id 

什麼應該被返回是一個數組的數組對象和計數,像這樣:

[ 
    [Person, int], 
    [Person, int], 
    ..., 
] 

你最好的選擇將是使這對你PersonRepository存儲庫調用,像findPersonsWithFriendCount(),這看起來像:

public function findPersonsWithFriendCount() 
{ 
    $persons = array(); 

    $query = $this->_em->createQuery(' 
     SELECT p, COUNT(p.friends) 
     FROM AppBundle\Entity\Person p 
     LEFT JOIN p.friends f 
     GROUP BY p.id 
    '); 

    $results = $query->getResult(); 

    foreach ($results as $result) { 
     $person = $result[0]; 
     $person->setFriendsCount($result[1]); 

     $persons[] = $person; 
    } 

    return $persons; 
} 

請記住,您需要在您的Person對象上添加setFriendsCount()函數。您也可以編寫原生SQL查詢並使用result set mapping自動將原始結果的列映射到您的實體字段。

+0

非常感謝這個例子!確實有用 – RVandersteen

+0

請記住,這不應該是必要的。如果你只是明確地像這樣加入一個庫調用,你可以像往常一樣去除COUNT()和返回實體,然後把'return $ this-> friends-> count()'放在你的getFriendsCount()方法。如果你明確加入它不會添加另一個數據庫調用......如果你還沒有加載它們,它會。 –

+0

確實,我甚至可能不明確需要getFriendsCount()並在加入後使用getFriends() - > count(),我需要它。但是這種技術可能對某些特殊查詢有用。關於(非常)大量的關係和表現,你會做什麼?加入(並因此保溼)大量的實體只是爲了計數可能會減慢速度。只是想(寫)大聲:) – RVandersteen