Symfony/Doctrine 实体中的关系 COUNT

Symfony/Doctrine relation COUNT in entity

如标题所述,

我想 运行 1 个查询从 table 中获取结果以及它们各自关系的计数。

假设我有一个 Person 实体与 Friend 实体

OneToMany 关系

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 中完成并将 count 值存储到 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();

甚至将其标记为 extra lazy 以获取计数结果。

虽然这个 count relationships 示例很好地展示了我正在尝试做的事情。

(从 dql 填充实体的非 @ORM\Column 属性)

Doctrine 可以吗?

这是否违反了一些稳固的原则? (建议零售价?)

Cookie 表达您的想法 ;)

您可能只想 select 根据需要进行计数,如上文 $person->getFriends()->count(); 所述。但是,您可以同时 select 一个对象和一个计数(请参阅这些 Doctrine query examples),其中一个与您正在做的非常相似:

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 自动将原始结果的列映射到您的实体字段。