使用DQL根据ManyToMany关系进行COUNT(*)GROUP BY吗?

时间:2018-10-25 20:42:30

标签: php doctrine dql

我有两个实体 Person Skill ,其中 Person 可能具有多种技能。

/**
 * @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
 */
class Person
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Skill", inversedBy="people")
     */
    private $skills = [];

    // other fields and getters/setters
}

技能

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\SkillRepository")
 */
class Skill
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Person", mappedBy="skills")
     */
    private $people = [];

    // other fields and getters/setters
}

我有一个表格,可以按技能过滤人,每个技能都是一个复选框,我希望拥有该技能的人数以及复选框的标签。

结果是:

what i have

我使用以下本机查询使其工作:

SELECT s.id, COUNT(*) AS c
FROM skill s
JOIN person_skill ps   /* table required by the M2M relation between person and skill */
ON s.id = ps.skill_id
GROUP BY s.id

如您所见,我需要在ManyToMany表上进行JOIN以获得这些计数。

我该如何使用Doctrine的DQL而不是使用本机查询?

2 个答案:

答案 0 :(得分:1)

实际上,当映射具有关系的实体时,Doctrine使用名为ArrayCollection的自定义对象。

它带有许多方法,例如filter()和count()。

如果需要,可以向Array中添加一个方法,该方法将使用ArrayCollection(人员)的count方法。

要确保正确使用ArrayCollection,必须像下面这样更改Skill类:

class Skill
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Person", mappedBy="skills")
     */
    private $people; //<-- Removed the default array definition

    public function __construct()
    {
        $this->people = new ArrayCollection(); //Add this line in your constructor
    }

    public function countPeople()
    {
        return $this->people->count(); //Will return the number of people joined to the skill
    }

    // other fields and getters/setters
}

答案 1 :(得分:0)

好的,我找到了解决方法:

$rows = $this->_em->createQueryBuilder('s')
                  ->select('s.id, COUNT(p.id) AS c')
                  ->from(Skill::class, 's')
                  ->join('s.people', 'p')
                  ->groupBy('s.id')
                  ->getQuery()
                  ->getArrayResult();

它生成以下查询:

SELECT s0_.id AS id_0, COUNT(p1_.id) AS sclr_1 
FROM skill s0_ 
INNER JOIN person_skill p2_
ON s0_.id = p2_.skill_id 
INNER JOIN person p1_ 
ON p1_.id = p2_.person_id 
GROUP BY s0_.id