Метод setFetchJoinCollection
Метод setFetchJoinCollection класса Paginator
включает или отключает режим выборки связанных
коллекций через JOIN. Первым параметром передаётся
булево значение: true включает режим,
false выключает. По умолчанию режим включён.
Метод возвращает текущий объект пагинатора, что
позволяет строить цепочки вызовов.
При пагинации запросов с JOIN по коллекциям
(например, OneToMany) одна и та же корневая
сущность может попасть в несколько строк результата.
Это приводит к неверному подсчёту элементов и
смещению страниц. Метод setFetchJoinCollection
говорит пагинатору, что нужно учитывать такие
дубликаты и корректно вычислять границы выборки.
Синтаксис
$paginator->setFetchJoinCollection(bool $fetchJoinCollection): self
Пример
Давайте создадим пагинатор для сущности Article
со связью OneToMany на сущность Comment
и включим режим выборки коллекций:
<?php
namespace App\Controller;
use App\Entity\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Doctrine\ORM\Tools\Pagination\Paginator;
class ArticleController extends AbstractController
{
#[Route('/articles', name: 'article_list')]
public function list(EntityManagerInterface $em): Response
{
$qb = $em->createQueryBuilder()
->select('a')
->from(Article::class, 'a')
->leftJoin('a.comments', 'c')
->addSelect('c');
$paginator = new Paginator($qb);
$paginator->setFetchJoinCollection(true);
$res = [];
foreach ($paginator as $article) {
$res[] = $article->getTitle();
}
return new Response(implode(', ', $res));
}
}
?>
Результат выполнения кода:
"article 1, article 2, article 3"
Пример
Давайте отключим режим выборки коллекций для
запроса без JOIN по коллекциям:
<?php
namespace App\Controller;
use App\Entity\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Doctrine\ORM\Tools\Pagination\Paginator;
class ArticleController extends AbstractController
{
#[Route('/articles/simple', name: 'article_simple')]
public function simple(EntityManagerInterface $em): Response
{
$qb = $em->createQueryBuilder()
->select('a')
->from(Article::class, 'a');
$paginator = new Paginator($qb);
$paginator->setFetchJoinCollection(false);
$res = [];
foreach ($paginator as $article) {
$res[] = $article->getTitle();
}
return new Response(implode(', ', $res));
}
}
?>
Результат выполнения кода:
"article 1, article 2, article 3"
Смотрите также
-
класс
Paginator,
который выполняет пагинацию Doctrine-запросов -
метод
getIterator,
который возвращает итератор по элементам страницы -
метод
count,
который возвращает общее количество элементов -
константа
HINT_FETCH_JOIN_COLLECTION,
которая задаёт режим выборки коллекций через подсказку запроса