denyAccessUnlessGranted('ROLE_VIEWER'); $constructeur = $this->em->find(Constructeur::class, $id); if (!$constructeur) { return new JsonResponse( ['message' => 'Fournisseur introuvable.'], Response::HTTP_NOT_FOUND, ); } $bulk = $this->fetchAllStats(); return new JsonResponse($bulk[$id] ?? [ 'composantCount' => 0, 'pieceCount' => 0, 'machineCount' => 0, 'productCount' => 0, ]); } #[Route('/api/constructeurs/stats', name: 'api_constructeurs_stats_bulk', methods: ['GET'], priority: 1)] public function bulkStats(): JsonResponse { $this->denyAccessUnlessGranted('ROLE_VIEWER'); return new JsonResponse($this->fetchAllStats()); } /** @return array */ private function fetchAllStats(): array { $result = []; // Initialize all constructeurs with zero counts $allIds = $this->em->createQuery( 'SELECT c.id FROM App\Entity\Constructeur c', )->getSingleColumnResult(); foreach ($allIds as $id) { $result[$id] = [ 'composantCount' => 0, 'pieceCount' => 0, 'machineCount' => 0, 'productCount' => 0, ]; } // 4 bulk queries instead of 4N $counts = [ 'composantCount' => ComposantConstructeurLink::class, 'pieceCount' => PieceConstructeurLink::class, 'machineCount' => MachineConstructeurLink::class, 'productCount' => ProductConstructeurLink::class, ]; foreach ($counts as $key => $entityClass) { $rows = $this->em->createQuery( 'SELECT IDENTITY(l.constructeur) AS cid, COUNT(l.id) AS cnt FROM '.$entityClass.' l GROUP BY l.constructeur', )->getResult(); foreach ($rows as $row) { if (isset($result[$row['cid']])) { $result[$row['cid']][$key] = (int) $row['cnt']; } } } return $result; } }