2016-02-02 144 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