Я хочу написать запрос DQL, который выбирает сообщение и присоединяется к другому объекту.
Вот мой код:
$dql = '
SELECT p , h ,t ,m
FROM App:Post p
LEFT JOIN p.mentions m
LEFT JOIN p.tags t
LEFT JOIN p.file h
WHERE p.user
IN (
SELECT f FROM App:User u
JOIN u.followers f
WHERE u.id = :uid
)
OR p.user = :uid ';
$query = $this->getEntityManager()
->createQuery($dql)
->setMaxResults(5)
->setParameters(['uid' => $user->getId()])
->getArrayResult();
Но проблема в том, что setMaxResults не ограничивает Entity сообщений, а вместо этого ограничивает теги Entity на 5.
Вот мои два типа результатов:
1. с setMaxResults (не работает нормально)
2. с setMaxResults (работает нормально)
Что не так с моим кодом?






Я предлагаю запустить этот запрос (с ограничением) напрямую в БД. Вы увидите, что запрос возвращает 5 строк, но только с 3 уникальными сообщениями. Это связано с тем, что в одном сообщении может быть несколько тегов, поэтому каждая комбинация пост-тегов приведет к одной строке. Таким образом, 2 сообщения с 3 тегами в каждом будут содержать 6 строк. Установка лимита повлияет на количество строк, возвращаемых запросом, но не ограничивает магическим образом только количество сообщений. Дублированные сообщения в результате запроса удаляются при сопоставлении результата запроса с объектами, но на данный момент у вас есть только 3 уникальных сообщения.
Вероятно, вам следует запрашивать сообщения и теги отдельно и не использовать limit с отношениями «один-ко-многим» или «многие-многие».
Это ожидаемое поведение в доктрине при использовании setMaxResults () или setFirstResult () без пагинатора.
setMaxResults () фактически добавляет ПРЕДЕЛ SQL к произведенному запросу, он не ограничивает только корневую сущность, как вы ожидаете, но строки, возвращаемые запросом. Это означает, что по объединенным запросам он не будет делать то, что вы хотите.
По данным Элементы первого и максимального результатов
If your query contains a fetch-joined collection specifying the result limit methods are not working as you would expect. Set Max Results restricts the number of database result rows, however in the case of fetch-joined collections one root entity might appear in many rows, effectively hydrating less than the specified number of results.
Что вы можете сделать для достижения желаемого, так это использовать Пагинатор в своем запросе:
$query = $this->getEntityManager()
->createQuery($dql)
->setMaxResults(5)
->setParameters(['uid' => $user->getId()]);
$paginator = new Paginator($query, $fetchJoinCollection = true);
$c = count($paginator);
foreach ($paginator as $post) {
}
Из ссылки на документацию Paginator выше:
Paginating Doctrine queries is not as simple as you might think in the beginning. If you have complex fetch-join scenarios with one-to-many or many-to-many associations using the "default" LIMIT functionality of database vendors is not sufficient to get the correct results.
Также обратите внимание, что:
By default the pagination extension does the following steps to compute the correct result:
DISTINCT.DISTINCT, чтобы найти все идентификаторы объекта на текущей странице.This behavior is only necessary if you actually fetch join a to-many collection. You can disable this behavior by setting the $fetchJoinCollection flag to false; in that case only 2 instead of the 3 queries described are executed. We hope to automate the detection for this in the future.
спасибо за ваш ответ, этот ответ решил мою проблему, но появляется другая проблема, и это когда я пытаюсь сериализовать данные, сервер зависает и застревает навсегда
@ mR.Rian. Возможно, у вас есть круговая ссылка, например, Post -> Tags -> Posts, которая используется при сериализации, но для этого, я думаю, вам следует задать новый вопрос.
Это отличный ответ. Спасибо
нет setMaxResults ограничивает теги @Aurelien