我有两个实体 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
}
我有一个表格,可以按技能过滤人,每个技能都是一个复选框,我希望拥有该技能的人数以及复选框的标签。
结果是:
我使用以下本机查询使其工作:
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而不是使用本机查询?
答案 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