实体中的Symfony/Doctrine关系COUNT

RVa*_*een 5 entity count relationship symfony doctrine-orm

正如标题所述,

我想运行1个查询来从表中获取结果以及各自关系的计数.

假设我有一个Person与实体有OneToMany关系的Friend实体

Person实体可能如下所示:

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

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的经典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
Run Code Online (Sandbox Code Playgroud)

现在我想知道这是否也可以在DQL中完成并将数值存储到Person实体中

可以说,我扩大Person实体,如:(请记住,这只是一个想法)

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

    protected $friendsCount;

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

    ...

    public function getFriendsCount()
    {
        return $this->friendsCount;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我无法找到如何从DQL填充实体中的计数值:

SELECT p, /* What comes here ? */
FROM AppBundle\Entity\Person p
LEFT JOIN p.friends f
GROUP BY p.id
Run Code Online (Sandbox Code Playgroud)

PS:我知道我可以这样做:

$person->getFriends()->count();
Run Code Online (Sandbox Code Playgroud)

甚至将它标记为额外的懒惰以获得计数结果.

我只是这个计算关系的例子很好地展示了我想要做的事情.

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

这可能与Doctrine有关吗?

这打破了一些坚实的原则吗?(SRP?)

饼干为你的虽然;)

Jas*_*man 6

您可能只想根据需要选择计数,如上所述$person->getFriends()->count();.但是,您可以同时选择对象和计数 - 请参阅这些Doctrine DQL示例,其中有一个与您正在执行的操作非常相似:

SELECT p, COUNT(p.friends)
FROM AppBundle\Entity\Person p
LEFT JOIN p.friends f
GROUP BY p.id
Run Code Online (Sandbox Code Playgroud)

应该返回的是带有对象和计数的数组数组,如下所示:

[
    [Person, int],
    [Person, int],
    ...,
]
Run Code Online (Sandbox Code Playgroud)

你最好的选择就是在你的电子邮件上进行调用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;
}
Run Code Online (Sandbox Code Playgroud)

请记住,您需要setFriendsCount()Person对象上添加一个函数.您还可以编写本机SQL查询并使用结果集映射自动将原始结果列映射到实体字段.

  • 我必须将原始查询更新为“SELECT p, COUNT(f) ...”才能使其正常工作。 (2认同)