РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
853 of 1361 menu

Хинт HINT_FETCH_JOIN_COLLECTION

Хинт HINT_FETCH_JOIN_COLLECTION - это константа класса Paginator, которая передаётся в метод paginate для управления стратегией загрузки данных. По умолчанию пагинатор выполняет отдельный запрос для подсчёта общего количества записей. Если пагинируемая сущность содержит коллекцию (связь OneToMany или ManyToMany), это может привести к проблеме N+1 запроса. Установка хинта HINT_FETCH_JOIN_COLLECTION заставляет пагинатор использовать JOIN для выборки коллекции в основном запросе, что снижает нагрузку на базу данных. Хинт передаётся четвёртым аргументом в метод paginate.

Синтаксис

Paginator::HINT_FETCH_JOIN_COLLECTION

Пример

Давайте создадим пагинатор для сущности Article и передадим хинт HINT_FETCH_JOIN_COLLECTION:

<?php namespace AppController; use AppEntityArticle; use DoctrineORMEntityManagerInterface; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentHttpFoundationResponse; use SymfonyComponentRoutingAttributeRoute; use KnpComponentPagerPaginatorInterface; use KnpComponentPagerPaginator; class ArticleController extends AbstractController { #[Route('/articles', name: 'article_list')] public function list(EntityManagerInterface $em, PaginatorInterface $paginator): Response { $dql = 'SELECT a FROM AppEntityArticle a'; $query = $em->createQuery($dql); $res = $paginator->paginate( $query, 1, 10, [ Paginator::HINT_FETCH_JOIN_COLLECTION => true ] ); return $this->render('article/list.html.twig', [ 'pagination' => $res, ]); } } ?>

В результате пагинатор выполнит JOIN-запрос для выборки связанных коллекций, что позволит избежать дополнительных запросов при итерации по результатам.

Пример

Давайте сравним поведение пагинатора без хинта и с хинтом. Без хинта для каждой записи будет выполнен отдельный запрос на загрузку коллекции:

<?php namespace AppController; use AppEntityArticle; use DoctrineORMEntityManagerInterface; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentHttpFoundationResponse; use SymfonyComponentRoutingAttributeRoute; use KnpComponentPagerPaginatorInterface; class ArticleController extends AbstractController { #[Route('/articles/n-plus-one', name: 'article_n_plus_one')] public function nPlusOne(EntityManagerInterface $em, PaginatorInterface $paginator): Response { $dql = 'SELECT a FROM AppEntityArticle a'; $query = $em->createQuery($dql); $res = $paginator->paginate($query, 1, 10); foreach ($res as $article) { foreach ($article->getComments() as $comment) { echo $comment->getText(); } } return new Response('done'); } } ?>

Если у каждой статьи есть комментарии, то при итерации будет выполнен дополнительный запрос для каждой статьи. С хинтом HINT_FETCH_JOIN_COLLECTION коллекция загружается сразу:

<?php namespace AppController; use AppEntityArticle; use DoctrineORMEntityManagerInterface; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentHttpFoundationResponse; use SymfonyComponentRoutingAttributeRoute; use KnpComponentPagerPaginatorInterface; use KnpComponentPagerPaginator; class ArticleController extends AbstractController { #[Route('/articles/fetch-join', name: 'article_fetch_join')] public function fetchJoin(EntityManagerInterface $em, PaginatorInterface $paginator): Response { $dql = 'SELECT a FROM AppEntityArticle a'; $query = $em->createQuery($dql); $res = $paginator->paginate( $query, 1, 10, [ Paginator::HINT_FETCH_JOIN_COLLECTION => true ] ); foreach ($res as $article) { foreach ($article->getComments() as $comment) { echo $comment->getText(); } } return new Response('done'); } } ?>

Результат выполнения кода:

done

Смотрите также

  • класс Paginator,
    который выполняет пагинацию данных
  • метод setFetchJoinCollection,
    который включает fetch join для коллекций
  • метод getQuery,
    который возвращает пагинированный запрос
  • метод setUseOutputWalkers,
    который управляет обходом результатов
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить