Делаете COUNT (*) GROUP BY на основе отношения ManyToMany с использованием DQL? - PullRequest
0 голосов
/ 25 октября 2018

У меня есть две сущности Человек и Умение , где Человек может иметь несколько навыков.

Человек

/**
 * @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

Как видите, мне требуется JOIN для таблицы ManyToMany, чтобы получить эти значения.

Как я могу сделать это с помощью DQL Doctrine вместо использования нативного запроса?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Хорошо, я нашел решение:

$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
0 голосов
/ 26 октября 2018

На самом деле, при сопоставлении сущностей со связями, Doctrine использует пользовательский объект с именем ArrayCollection .

. Он поставляется со многими методами, такими как filter () и count ().

Вы можете добавить метод к своей сущности умения, если хотите, чтобы он использовал метод count ArrayCollection (people).

Чтобы убедиться, что вы используете 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
}
...