Optimize N+1 queries: batch billets, soldCounts, paid orders with items

- AccountController: single query for all billets by categories, single
  GROUP BY query for sold counts, eager-load items on paid orders
- HomeController: single query for all buyable billets of active categories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-22 20:13:31 +01:00
parent 0772e618da
commit 0e79c65966
3 changed files with 40 additions and 16 deletions

View File

@@ -374,13 +374,29 @@ class AccountController extends AbstractController
['position' => 'ASC'],
);
$allBillets = $em->getRepository(Billet::class)->findBy(['category' => $categories], ['position' => 'ASC']);
$billets = [];
$billetIds = [];
foreach ($allBillets as $billet) {
$catId = $billet->getCategory()->getId();
$billets[$catId][] = $billet;
$billetIds[] = $billet->getId();
}
$soldCounts = [];
foreach ($categories as $category) {
$categoryBillets = $em->getRepository(Billet::class)->findBy(['category' => $category], ['position' => 'ASC']);
$billets[$category->getId()] = $categoryBillets;
foreach ($categoryBillets as $billet) {
$soldCounts[$billet->getId()] = $em->getRepository(BilletOrder::class)->count(['billet' => $billet]);
if ($billetIds) {
$rows = $em->createQueryBuilder()
->select('IDENTITY(bo.billet) AS billetId, COUNT(bo.id) AS cnt')
->from(BilletOrder::class, 'bo')
->where('bo.billet IN (:ids)')
->setParameter('ids', $billetIds)
->groupBy('bo.billet')
->getQuery()
->getArrayResult();
foreach ($rows as $row) {
$soldCounts[$row['billetId']] = (int) $row['cnt'];
}
}
@@ -390,7 +406,16 @@ class AccountController extends AbstractController
: $em->getRepository(BilletBuyer::class)->findBy(['event' => $event], ['createdAt' => 'DESC']);
$eventOrders = $paginator->paginate($ordersQuery, $request->query->getInt('page', 1), 20);
$paidEventOrders = $em->getRepository(BilletBuyer::class)->findBy(['event' => $event, 'status' => BilletBuyer::STATUS_PAID]);
$paidEventOrders = $em->createQueryBuilder()
->select('o', 'i')
->from(BilletBuyer::class, 'o')
->leftJoin('o.items', 'i')
->where('o.event = :event')
->andWhere('o.status = :status')
->setParameter('event', $event)
->setParameter('status', BilletBuyer::STATUS_PAID)
->getQuery()
->getResult();
$eventStats = $this->computeEventStats($paidEventOrders);
return $this->render('account/edit_event.html.twig', [