Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD
PHP & SGBD Forum d'entraide sur les SGBD avec PHP. Avant de poster : FAQ BDD, toutes les FAQ PHP, cours BDD et sources BDD
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/03/2008, 10h10   #1
Membre du Club
 
Inscription : mars 2008
Messages : 37
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 37
Points : 63
Points : 63
Par défaut [SQL] Nombre de requête élevé pour un menu

Bonjour à tous,
je développe actuellement un site personnel en PHP.
Là je travaille sur le menu principale.
Ce menu se compose de sous-menus, qui peuvent contenir des sous-menus, etc...
Tous le menus est enregistré dans une table de ma base de donnée (MySql), dont voici la structure (j'ai enlevé les colonnes inutiles) :
Code :
1
2
3
4
5
6
7
8
CREATE TABLE `menu` (
  `id_menu` int(11) NOT NULL auto_increment,
  `nom_menu` varchar(100) NOT NULL,
  `ordre_menu` int(11) NOT NULL,
  `id_menu_pere` int(11) NOT NULL,
  `nb_sous_menu` int(11) NOT NULL,
  PRIMARY KEY  (`id_menu`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=52 ;
Tout mon menu doit être placé dans un array, qui contiendra les menus, puis les sous-menus, dans des array, etc...
Voici le code actuelle :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function sous_menu($menu_pere)
{
	global $BdD;
	$sous_menu = Array();
	$retour_sous_menu = $BdD->mysql_query('SELECT * FROM menu WHERE id_menu_pere='.$menu_pere['id_menu'].' ORDER BY ordre_menu');
	while($donnee_sous_menu = mysql_fetch_array($retour_sous_menu))
	{
		if($donnee_sous_menu['nb_sous_menu']!=0)
			$donnee_sous_menu['sous_menu'] = sous_menu($donnee_sous_menu);
		array_push($sous_menu,$donnee_sous_menu);
	}
	return $sous_menu;
}
$menu = Array();
$retour_menu_princ = $BdD->mysql_query('SELECT * FROM menu WHERE id_menu_pere=0 ORDER BY ordre_menu');
while($donnee_menu_princ = mysql_fetch_array($retour_menu_princ))
{
	if($donnee_menu_princ['nb_sous_menu']!=0)
		$donnee_menu_princ['sous_menu'] = sous_menu($donnee_menu_princ);
	array_push($menu,$donnee_menu_princ);
}
Comme vous pouvez le voir, pour chaque sous-menus, je fais une requête SQL, et pour l'heure cette page me fais plus de 30 requêtes sql, pour m'afficher ce menu.

Pouvez vous m'aider à améliorer ce script ?
Merci d'avance pour vos réponse et pour votre aide.

Information : Le fait de mettre le menu de la sorte dans un array est très important car j'utilise le template Smarty pour l'affichage de mes pages.

EDIT :
Descriptions des champs :
id_menu (Id du menu)
nom_menu (Nom a afficher)
ordre_menu (ordre d'affichage, 1, 2, 3, etc... )
id_menu_pere (id de menu a qui appartient ce menu, 0 pour le premier menu)
nb_sous_menu (Nombre de sous-menu, 0 si pas de sous-menus)
Droup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 14h22   #2
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
Dans ton cas tu n'auras pas tellement le choix. A chaque niveau tu dois faire une requêtes. Je me suis retrouvé dans la même problèmatique que toi. Seul solution que j'ai trouvé qui permet de le faire en une seul requête.
C'est d'utiliser un champs texte ayant se format.
111
111.111
111.112
111.113
111.113.111
112
112.111
Avec un champs qui à ce genre d'information il facile de savoir le niveau, la profondeur, son parent. Bref en une seul requête avec un LIKE '111.___' ou LIKE '111.%' ça permet de chercher très facilement. De pouvoir boucler sur les niveaux. Ceci avec qu'une requête SQL.
Je ne fait rien pour générer ces chiffres je le gère automatiquement dans une procédure stocké .
__________________
Mon avatar ? Ce n'est rien, c'est juste la tête que je fais lorsque je vois un code complètement frappa dingue !...
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h16   #3
Membre du Club
 
Inscription : mars 2008
Messages : 37
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 37
Points : 63
Points : 63
Je n'ai pas très bien compris comment tu as fait.

Mais j'ai trouvé une solution, pour n'en faire qu'une seule, le problème c'est que je parcours la table en entier, pour chaque menu. Qu'est-ce qui est le mieux, faire une requête sql, mais alourdir le code php, ou faire plusieurs requêtes mais avoir un code php rapide ?

Voici comment j'ai fait pour ceux que ça intéresse :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
function sous_menu($menu_pere)
{
	global $BdD;
	global $donnee_menu_p;
	$sous_menu = Array();
	foreach($donnee_menu_p as $donnee_sous_menu)
		if($donnee_sous_menu['id_menu_pere']==$menu_pere['id_menu'])
		{
			if($donnee_sous_menu['nb_sous_menu']!=0)
				$donnee_sous_menu['sous_menu'] = sous_menu($donnee_sous_menu);
			array_push($sous_menu,$donnee_sous_menu);
		}
 
	return $sous_menu;
}
$menu = Array();
$retour_menu = $BdD->mysql_query('SELECT * FROM menu ORDER BY ordre_menu');
$donnee_menu_p = Array();
while($donnee_menu = mysql_fetch_array($retour_menu))
	array_push($donnee_menu_p,$donnee_menu);
 
foreach($donnee_menu_p as $donnee_menu_princ)
	if($donnee_menu_princ['id_menu_pere']==0)
	{
		if($donnee_menu_princ['nb_sous_menu']!=0)
			$donnee_menu_princ['sous_menu'] = sous_menu($donnee_menu_princ);
		array_push($menu,$donnee_menu_princ);
	}
Droup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h40   #4
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
Je dirais qu'il est préférable d'"allourdir" le php que la base de données mais le bute c'est qu'il faut être claire lorsque tu reviens dessus ou une autre personne.
La technique que je te proposais était de placer le plan pour chaque enregistrement.
Exemple : 111.112.111 signifie que l'enregistrement courant est dans une deuxième profondeur. Sont parent c'est le 112 et le parent de celui-ci est 111. Bref, c'est un moyen simple de récolter des informations sur un élément hiérarchisé.
Donc si tu fais :
Code :
SELECT * FROM maTable WHERE level LIKE '111%' ORDER BY level
Cela va afficher tout les fils de l'élement 111 Donc
1 : 111
2 : 111.112
3 : 111.112.111

Dans le tableau que tu parcours tu peux faire tes sous menu à partir du moment ou tu change de profondeur. Là c'est facile à les détecter.
__________________
Mon avatar ? Ce n'est rien, c'est juste la tête que je fais lorsque je vois un code complètement frappa dingue !...
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h54   #5
Membre du Club
 
Inscription : mars 2008
Messages : 37
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 37
Points : 63
Points : 63
Ok, là je vois comment tu veux le faire, et donc pour chaque menu tu fais une requête sql.
Mais si je fais ça de la sorte, je vais rencontrer un autre problème (possible à réaliser, mais là aussi lourd), qui est la gestion de ce menu.
En fait j'ai une page d'administration qui me permet d'administrer ce menu, ainsi que l'ordre d'affichage des menus, et des sous-menus.
Ainsi pour cette exemple :
111
111.111
111.111.111
111.111.112
111.112
112
113
113.111

Si je passe le 2ème menu en premier il ma faudra tout changer de la sorte :
112
112.111
112.111.111
112.111.112
112.112
111
113
113.111

Je pense que tu vois où est le problème à ce niveau.

Merci pour tes réponses.
Droup est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 17h09   #6
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
C'est un risque en effet. Mais je me préocupe pas de cela. J'ai un champs ordre. C'est celle-ci que je me base. Le level permet seulement de savoir à qui est ton parent et de connaitre son origine.
Personnellement j'ai pas terminé lorsque je fais une modificiation de menu mais c'est prévus. Comme je te le disais, je suis dans le même cas que toi. Mon cas est que ma menu peut se retrouver dans un autre sous menu. Il faut que je fasse l'algo pour cela.
En gros c'est le principe de la taxinomie ou taxonomie.
__________________
Mon avatar ? Ce n'est rien, c'est juste la tête que je fais lorsque je vois un code complètement frappa dingue !...
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h56.


 
 
 
 
Partenaires

Hébergement Web