2016-02-02 5 views
3

Как видно из названия государств,Symfony/Doctrine отношение COUNT в сущности

Я хотел бы выполнить 1 запрос, чтобы получить результаты из таблицы с графом их соответствующих отношений.

Допустим, у меня есть Person сущность с отношения OneToMany с Friend лица

Человек лица может выглядеть примерно следующим:

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, а также и хранения счета значение в Person Entity

Допустим, я расширить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: Я KNO w Я мог бы просто:

$person->getFriends()->count(); 

И даже отметьте его как лишний, чтобы получить результат подсчета.

Я только что это кол-во отношений пример хорошо продемонстрировал то, что я пытаюсь сделать.

(Который заселение не являющиеся @ORM\Column свойств аудируемых от DQL)

возможен ли это с доктриной?

Является ли это нарушением некоторых твердых принципов? (SRP?)

Cookie для thoughs;)

ответ

4

Вы, вероятно, просто хочу, чтобы выбрать количество, как вам это нужно, как описано выше, с $person->getFriends()->count();.Тем не менее, вы можете выбрать как объект и подсчет в то же время - увидеть эти Doctrine DQL example с, есть одна очень похожа на то, что вы делаете:

SELECT p, COUNT(p.friends) 
FROM AppBundle\Entity\Person p 
LEFT JOIN p.friends f 
GROUP BY p.id 

Что должно быть возвращено обратно массив массивов с объект и сосчитать, например, так:

[ 
    [Person, int], 
    [Person, int], 
    ..., 
] 

лучше всего было бы сделать, что в Repository вызова на вашем 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; 
} 

Имейте в виду, что вам нужно добавить функцию setFriendsCount() на ваш объект Person. Вы также можете написать собственный SQL-запрос и использовать result set mapping, чтобы автоматически сопоставлять столбцы исходного результата с полями вашего объекта.

+0

Большое спасибо за этот пример! Действительно полезно – RVandersteen

+0

Имейте в виду, что это не обязательно. Если вы просто явно присоединяетесь к вызову репозитория, как это, вы можете просто удалить 'COUNT()' и возвращать сущности, как обычно, а затем поместить 'return $ this-> friends-> count()' в свой 'getFriendsCount()' метод. Если вы явно присоединитесь к нему, он не добавит другого вызова базы данных ... и если вы еще не загрузили их, это произойдет. –

+0

Действительно, я даже не могу явно использовать getFriendsCount() и использовать getFriends() -> count(), где мне это нужно после объединения. Но эта техника может оказаться полезной для некоторых специальных запросов. Каким бы вы ни были (очень) большое количество отношений и производительности. Присоединение (и, следовательно, увлажнение) большого количества сущностей только для того, чтобы получить счет, может замедлить работу. Просто думать (писать) вслух :) – RVandersteen

Смежные вопросы