src/Controller/HomeController.php line 412
<?phpnamespace App\Controller;use App\Entity\Metier;use App\Entity\Secteur;use App\Entity\Etablissement;use App\Entity\DirectionRegionale;use App\Entity\Candidature;use Doctrine\ORM\EntityManagerInterface;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\Routing\Annotation\Route;class HomeController extends AbstractController{private $entityManager;public function __construct(EntityManagerInterface $entityManager){$this->entityManager = $entityManager;}#[Route('/', name: 'app_home')]public function index(Request $request): Response{// Paramètres pour les métiers$pageMetier = $request->query->getInt('page-metier', 1);$limitMetier = 9;$rechercheMetier = $request->query->get('recherche-metier', '');$secteurId = $request->query->get('secteur-id', '');// Paramètres pour les établissements$pageEtablissement = $request->query->getInt('page-etablissement', 1);$limitEtablissement = 9;$rechercheEtablissement = $request->query->get('recherche-etablissement', '');$directionId = $request->query->get('direction-id', '');// ========== REQUÊTE POUR LES MÉTIERS ==========$metierQuery = $this->entityManager->getRepository(Metier::class)->createQueryBuilder('m')->leftJoin('m.secteur', 's')->leftJoin('m.etablissementMetiers', 'em')->leftJoin('em.etablissement', 'e')->addSelect('s', 'em', 'e');if (!empty($rechercheMetier)) {$metierQuery->andWhere('m.nom LIKE :recherche')->setParameter('recherche', '%' . $rechercheMetier . '%');}if (!empty($secteurId)) {$metierQuery->andWhere('s.id = :secteurId')->setParameter('secteurId', $secteurId);}// Compter le total des métiers$totalMetiers = (clone $metierQuery)->select('COUNT(DISTINCT m.id)')->getQuery()->getSingleScalarResult();// Récupérer les métiers paginés$metiers = $metierQuery->select('m', 's', 'em', 'e')->setFirstResult(($pageMetier - 1) * $limitMetier)->setMaxResults($limitMetier)->orderBy('m.nom', 'ASC')->getQuery()->getResult();// ========== REQUÊTE POUR LES ÉTABLISSEMENTS ==========// Compter le total des établissements avec les filtres$countQuery = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->select('COUNT(DISTINCT e.id)');if (!empty($directionId)) {$countQuery->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->andWhere('d.id = :directionId')->setParameter('directionId', $directionId);}if (!empty($rechercheEtablissement)) {$countQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche', '%' . $rechercheEtablissement . '%');}$totalEtablissements = $countQuery->getQuery()->getSingleScalarResult();// Récupérer les IDs des établissements pour cette page (pour éviter les doublons)$idQuery = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->select('e.id')->orderBy('e.nom', 'ASC');if (!empty($directionId)) {$idQuery->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->andWhere('d.id = :directionId')->setParameter('directionId', $directionId);}if (!empty($rechercheEtablissement)) {$idQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche', '%' . $rechercheEtablissement . '%');}$ids = $idQuery->setFirstResult(($pageEtablissement - 1) * $limitEtablissement)->setMaxResults($limitEtablissement)->getQuery()->getResult();$etablissementIds = array_column($ids, 'id');// Récupérer les établissements complets avec leurs relations$etablissements = [];if (!empty($etablissementIds)) {$etablissements = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->leftJoin('e.etablissementMetiers', 'em')->leftJoin('em.metier', 'm')->addSelect('l', 'd', 'em', 'm')->where('e.id IN (:ids)')->setParameter('ids', $etablissementIds)->orderBy('e.nom', 'ASC')->getQuery()->getResult();}// Données pour les filtres$secteurs = $this->entityManager->getRepository(Secteur::class)->findBy([], ['nom' => 'ASC']);$directions = $this->entityManager->getRepository(DirectionRegionale::class)->findBy([], ['nom' => 'ASC']);// Statistiques globales$stats = ['metiers' => $this->entityManager->getRepository(Metier::class)->count([]),'etablissements' => $this->entityManager->getRepository(Etablissement::class)->count([]),'secteurs' => $this->entityManager->getRepository(Secteur::class)->count([]),'places' => $this->getTotalPlaces(),'candidatures' => $this->entityManager->getRepository(Candidature::class)->count([])];$partenaires = $this->getPartenaires();return $this->render('index.html.twig', [// Données pour les métiers'metiers' => $metiers,'secteurs' => $secteurs,'totalMetiers' => $totalMetiers,'limitMetier' => $limitMetier,'pageMetierActuelle' => $pageMetier,'rechercheMetier' => $rechercheMetier,'secteurSelectionne' => $secteurId,// Données pour les établissements'etablissements' => $etablissements,'directions' => $directions,'totalEtablissements' => $totalEtablissements,'limitEtablissement' => $limitEtablissement,'pageEtablissementActuelle' => $pageEtablissement,'rechercheEtablissement' => $rechercheEtablissement,'directionSelectionnee' => $directionId,// Statistiques globales'stats' => $stats,'partenaires' => $partenaires,]);}private function getTotalPlaces(): int{$conn = $this->entityManager->getConnection();$sql = 'SELECT SUM(nbrplace) as total FROM etablissement_metier';$result = $conn->executeQuery($sql)->fetchAssociative();return (int) ($result['total'] ?? 0);}#[Route('/load-metiers', name: 'app_load_metiers', methods: ['GET'])]public function loadMetiers(Request $request): JsonResponse{$page = $request->query->getInt('page', 1);$limit = $request->query->getInt('limit', 9);$recherche = $request->query->get('recherche', '');$secteurId = $request->query->get('secteur', '');$query = $this->entityManager->getRepository(Metier::class)->createQueryBuilder('m')->leftJoin('m.secteur', 's')->leftJoin('m.etablissementMetiers', 'em')->leftJoin('em.etablissement', 'e')->addSelect('s', 'em', 'e');if (!empty($recherche)) {$query->andWhere('m.nom LIKE :recherche')->setParameter('recherche', '%' . $recherche . '%');}if (!empty($secteurId)) {$query->andWhere('s.id = :secteurId')->setParameter('secteurId', $secteurId);}// Compter le total$total = (clone $query)->select('COUNT(DISTINCT m.id)')->getQuery()->getSingleScalarResult();// Récupérer les IDs paginés (pas de join collection pour éviter l'effet Cartésien)$idQuery = clone $query;$ids = array_column($idQuery->select('m.id')->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)->orderBy('m.nom', 'ASC')->getQuery()->getResult(),'id');// Charger les entités complètes uniquement pour ces IDs$metiers = [];if (!empty($ids)) {$metiers = $this->entityManager->getRepository(Metier::class)->createQueryBuilder('m')->leftJoin('m.secteur', 's')->leftJoin('m.etablissementMetiers', 'em')->leftJoin('em.etablissement', 'e')->addSelect('s', 'em', 'e')->where('m.id IN (:ids)')->setParameter('ids', $ids)->orderBy('m.nom', 'ASC')->getQuery()->getResult();}return $this->json(['html' => $this->renderView('partials/_metiers_cards.html.twig', ['metiers' => $metiers,]),'total' => $total,'page' => $page,'limit' => $limit]);}#[Route('/load-etablissements', name: 'app_load_etablissements', methods: ['GET'])]public function loadEtablissements(Request $request): JsonResponse{$page = $request->query->getInt('page', 1);$limit = $request->query->getInt('limit', 9);$directionId = $request->query->get('direction', '');$recherche = $request->query->get('recherche', '');// Compter le total$countQuery = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->select('COUNT(DISTINCT e.id)');if (!empty($directionId)) {$countQuery->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->andWhere('d.id = :directionId')->setParameter('directionId', $directionId);}if (!empty($recherche)) {$countQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche', '%' . $recherche . '%');}$total = $countQuery->getQuery()->getSingleScalarResult();// Récupérer les IDs pour cette page$idQuery = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->select('e.id')->orderBy('e.nom', 'ASC');if (!empty($directionId)) {$idQuery->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->andWhere('d.id = :directionId')->setParameter('directionId', $directionId);}if (!empty($recherche)) {$idQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche', '%' . $recherche . '%');}$ids = $idQuery->setFirstResult(($page - 1) * $limit)->setMaxResults($limit)->getQuery()->getResult();$etablissementIds = array_column($ids, 'id');// Récupérer les établissements complets$etablissements = [];if (!empty($etablissementIds)) {$etablissements = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->leftJoin('e.etablissementMetiers', 'em')->leftJoin('em.metier', 'm')->addSelect('l', 'd', 'em', 'm')->where('e.id IN (:ids)')->setParameter('ids', $etablissementIds)->orderBy('e.nom', 'ASC')->getQuery()->getResult();}return $this->json(['html' => $this->renderView('partials/_etablissements_cards.html.twig', ['etablissements' => $etablissements,]),'total' => $total,'page' => $page,'limit' => $limit]);}private function getPartenaires(): array{return [['nom' => 'Banque Mondiale','image' => 'image/partenaire/worldbank.png','lien' => 'https://www.banquemondiale.org'],['nom' => 'BCP Emploi','image' => 'image/partenaire/bcp.png','lien' => 'http://www.pejedec.org/']];}#[Route('/etablissements', name: 'app_etablissements_list')]public function etablissementsList(Request $request): Response{$recherche = $request->query->get('recherche', '');$directionId = $request->query->get('direction', '');$idQuery = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->select('e.id')->orderBy('e.nom', 'ASC');if (!empty($directionId)) {$idQuery->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->andWhere('d.id = :directionId')->setParameter('directionId', $directionId);}if (!empty($recherche)) {$idQuery->andWhere('e.nom LIKE :recherche')->setParameter('recherche', '%' . $recherche . '%');}$ids = array_column($idQuery->getQuery()->getResult(), 'id');$etablissements = [];if (!empty($ids)) {$etablissements = $this->entityManager->getRepository(Etablissement::class)->createQueryBuilder('e')->leftJoin('e.localite', 'l')->leftJoin('l.directionRegionale', 'd')->leftJoin('e.etablissementMetiers', 'em')->leftJoin('em.metier', 'm')->addSelect('l', 'd', 'em', 'm')->where('e.id IN (:ids)')->setParameter('ids', $ids)->orderBy('e.nom', 'ASC')->getQuery()->getResult();}$directions = $this->entityManager->getRepository(DirectionRegionale::class)->findBy([], ['nom' => 'ASC']);return $this->render('etablissement/list.html.twig', ['etablissements' => $etablissements,'directions' => $directions,'total' => count($ids),'recherche' => $recherche,'directionSelectionnee' => $directionId,]);}#[Route('/metiers', name: 'app_metiers_list')]public function metiersList(Request $request): Response{$recherche = $request->query->get('recherche', '');$secteurId = $request->query->get('secteur', '');// Step 1: get IDs only (no collection joins) to avoid Cartesian product in memory$idQuery = $this->entityManager->getRepository(Metier::class)->createQueryBuilder('m')->select('m.id')->leftJoin('m.secteur', 's')->orderBy('m.nom', 'ASC');if (!empty($recherche)) {$idQuery->andWhere('m.nom LIKE :recherche')->setParameter('recherche', '%' . $recherche . '%');}if (!empty($secteurId)) {$idQuery->andWhere('s.id = :secteurId')->setParameter('secteurId', $secteurId);}$ids = array_column($idQuery->getQuery()->getResult(), 'id');// Step 2: load full entities with joins only for the matched IDs$metiers = [];if (!empty($ids)) {$metiers = $this->entityManager->getRepository(Metier::class)->createQueryBuilder('m')->leftJoin('m.secteur', 's')->leftJoin('m.etablissementMetiers', 'em')->leftJoin('em.etablissement', 'e')->addSelect('s', 'em', 'e')->where('m.id IN (:ids)')->setParameter('ids', $ids)->orderBy('m.nom', 'ASC')->getQuery()->getResult();}$secteurs = $this->entityManager->getRepository(Secteur::class)->findBy([], ['nom' => 'ASC']);return $this->render('metier/list.html.twig', ['metiers' => $metiers,'secteurs' => $secteurs,'total' => count($ids),'recherche' => $recherche,'secteurSelectionne' => $secteurId,]);}}