Passer de 23 à 2 requêtes pour le même résultat
L'exemple traité ici concerne les menus déroulants de l'annuaire, mais est valable pour tous les autres menus déroulants gérés par base de donnée (catégories des articles, etc.)
Fichier admin/links.php, function links() >> // Add a New Link to Database
Nous avons dans cette fonction la création d'un menu déroulant avec les catégories de votre annuaire et les sous-catégories associées, le tout affiché par ordre alphabétique des catégories et des sous-catégories.
Pour ce faire, nous avons tout d'abord une 1ère requête répertoriant nos catégories.
On lance une boucle pour afficher ces catégories, à l'intérieur de laquelle se trouve une seconde boucle contenant une nouvelle requête afin de répertorier les sous-catégories. Cette dernière sera donc répétée autant de fois que vous avez de catégories principales.
Si vous avez par exemple 10 catégories dans votre annuaire, vous exécuterez 1 + 10 requêtes SQL !
Il est possible de faire la même opération avec 1 seule requête et 1 seule boucle !
Le code actuel :
$result=mysql_query("select cid, title from links_categories order by title");
echo 'Catégorie : <select class="TEXTBOX_STANDARD" name="cat">';
while(list($cid, $title) = mysql_fetch_row($result)) {
echo '<option value="'.$cid.'">'.$title.'</option>';
$result2=mysql_query("select sid, title from links_subcategories where cid='$cid' order by title");
while(list($sid, $stitle) = mysql_fetch_row($result2)) {
echo "<option value=\"$cid-$sid\">$title / $stitle</option>";
}
}
Code optimisé :
$menu_deroulant=mysql_query("select c.cid, c.title, s.sid, s.title from links_categories c, links_subcategories s where c.cid=s.cid order by 2,4");
echo 'Catégorie : <select class="TEXTBOX_STANDARD" name="cat">';
while(list($cid, $title, $sid, $stitle) = mysql_fetch_row($menu_deroulant)) {
if ($affiche!=$cid) {
echo '<option value="'.$cid.'">'.$title.'</option>';
}
echo '<option value="'.$cid.'-'.$sid.'">'.$title.' / '.$stitle.'</option>';
$affiche=$cid;
}
< br>
Explications :
"select c.cid, c.title, s.sid, s.title from links_categories c, links_subcategories s where c.cid=s.cid order by 2,4"
Dans cette même requête, je vais chercher tous les résultats dont nous avons besoin dans les 2 tables qui nous intéressent.
c.cid désigne par exemple le champ
cid de la table
c définie plus loin : from links_categories
c.
c.title provient également de la table
c, donc
links_categories,
s.sid et
s.title de la table
s soit la table
links_subcategories définie de la même manière à la suite de
links_categories.
where c.cid=s.cid sert à trier les résultats. Sans cette clause, vous obtiendriez pour chaque catégorie l'ensemble des sous-catégories, y compris celles des autres catégories. Vous pouvez faire un essai en supprimant cette clause pour constater la différence.
order by 2,4 permet le classement par ordre alphabétique, en priorité sur les titres des catégories (2), puis des sous-catégories.

La boucle !
Afin d'éviter de voir apparaitre le nom d'une catégorie devant chaque sous-catégorie correspondant, j'ai ajouté la condition
if ($affiche!=$cid) suivi de l'affichage de la catégorie.
- Au premier passage de la boucle,
$affiche n'est pas encore définie. La condition s'en trouve remplie donc la catégorie est affichée.
- A la suite, toujours au premier passage de la boucle, j'affiche la 1ère sous-catégorie.
- En fin de boucle, je définit
$affiche comme étant égale à l'ID de la catégorie.
- Au second passage de la boucle, la catégorie est toujours la même, avec cette fois une 2ème sous-catégorie à afficher.
$cid à toujours la même valeur,
$affiche étant alors égale à
$cid, la condition n'est plus remplie, donc pas d'affichage de la catégorie, mais seulement de la sous-catégorie suivante.
- ...
Lorsque toutes les sous-catégories sont parcourues, on change de catégorie (
$cid),
$affiche est toujours égal au
$cid précédant et la condition pour l'affichage de la catégorie se trouve à nouveau remplie.
Ce n'est pas finit !
Plus loin sur notre page est afficher à nouveau ce même menu déroulant, avec en prime cette fois une requête qui ira vérifier la présence de catégories
Pour le faire maintenant mais pas la 1ère fois ?
Mieux, à quoi sert un annuaire s'il ne contient pas de catégories ? Peu importe, nous faisons tous nos boulettes. C'était pour voir si l'on suivait
Ça ce passe juste après
// Modify Category
On peut donc commencer par supprimer la 1ère requête servant à compter le nombre de catégories et indirectement à vérifier leur présence.
Ne pas oublier d'enlever la condition associée.
Par simple précaution j'ai fait le choix d'initialiser la variable
$affiche ayant toujours comme valeur le dernier ID de catégories. Ce n'est normalement pas utile puisque nous repartons avec notre 1ère valeur.
Ce qui nous donne :
// Modify Category
echo '<table width="100%" cellspacing="2" cellpadding="2" border="0"><tr><td class="HEADER">';
echo 'Modifier la Catégorie';
echo '</td></tr></table>';
echo '<form method="post" action="admin.php">';
echo 'Catégorie : <select class="TEXTBOX_STANDARD" name="cat">';
$menu_deroulant=mysql_query("select c.cid, c.title, s.sid, s.title from links_categories c, links_subcategories s where c.cid=s.cid order by 2,4");
$affiche='';
while(list($cid, $title, $sid, $stitle) = mysql_fetch_row($menu_deroulant)) {
if ($affiche!=$cid) {
echo '<option value="'.$cid.'">'.$title.'</option>';
}
echo '<option value="'.$cid.'-'.$sid.'">'.$title.' / '.$stitle.'</option>';
$affiche=$cid;
}
< br>
Toujours en prenant l'exemple d'un annuaire avec 10 catégories, nous avions :

1 + 10 =11 requêtes

1 (vérif) + 1 + 10 = 12 requêtes
Ce qui nous faisait bien un total de 23 requêtes SQL sur une même page contre 2 maintenant !
[ Message modifié par Freud le 26-09-2008 à 02:14 ]