Vendredi soir, la taverne affiche complet. Bruna a ajouté à la carte le festin du vendredi, vingt-quatre plats, et les ingrédients s'affichent désormais sur la carte. Résultat : la page /menu se traîne, et le serveur de base de données fume plus que le Piment de feu.
Pipin a installé un compteur : en bas à droite de chaque page, le nombre de requêtes SQL qu'elle a coûté. Ouvrez l'aperçu.
Le problème N+1
Le template parcourt les catégories, puis les plats de chaque catégorie, puis les ingrédients de chaque plat. Doctrine charge les relations paresseusement : il n'interroge la base qu'au moment où on touche à une collection. Cela donne :
- 1 requête pour les catégories ;
- N requêtes, une par catégorie, pour ses plats ;
- encore une par plat, pour ses ingrédients.
Chaque ligne semble anodine, mais le nombre de requêtes grandit avec la carte.
Votre mission
/menudoit charger toute la carte (catégories, plats, ingrédients) en une seule requête ;- dans le même ordre qu'avant : catégories par position, plats du moins cher au plus cher, ingrédients par ordre alphabétique ;
- sans rien perdre : une catégorie encore vide ou un plat sans ingrédient restent à la carte ;
- même chose pour la carte d'un budget (
/menu?budget=5).
Le template, lui, ne change pas : c'est la requête qui doit apporter d'un coup tout ce qu'il va lire.