Affichage catégories/sous-catégories

Eléphant du PHP | 153 Messages

30 août 2006, 13:48

Bonjour à tous,

Je souhaite afficher un menu (catégories/sous-catégories) de cette manière :

Menu normal.
|------Cat A <--- catégorie parincipale
|------Cat B <--- catégorie parincipale
|------Cat C <--- catégorie parincipale
|------Cat D <--- catégorie parincipale


On clique sur une cat. principale, affichage des sous-catégories correspondantes.
|------Cat A
|--Cat A1 <--- sous-catégories
|--Cat A2
|--Cat A3
|--Cat A4
|------Cat B
|------Cat C
|------Cat D


On clique sur une autre cat. principale, affichage des sous-catégories correspondant à celle-ci.
|------Cat A
|------Cat B
|------Cat C
|--Cat C1 <--- sous-catégories
|--Cat C2
|--Cat C3
|--Cat C4
|------Cat D

Voici comment est agencée ma bdd :

`categorie_id` int(11) NOT NULL auto_increment,
`categorie_parent_id` int(11) NOT NULL default '0',
`categorie_nom` varchar(32) NOT NULL default '',
`categorie_description` varchar(64) NOT NULL default '',
`categorie_image` varchar(64) default NULL,
PRIMARY KEY (`categorie_id`),
KEY `id_categorie_parent_id` (`categorie_parent_id`)

Je pense ne pas avoir de problème pour faire afficher les catégories (quoi que je préfère attendre vos réponses, afin de ne pas partir vers un mauvais développement), mais je n'ai aucune idée de comment faire afficher les sous-catégories avec la façon dont je veux que cela se comporte.

Merci pour votre aide.

Eléphant du PHP | 172 Messages

30 août 2006, 14:07

Salut,

Avec ton shéma, je pense en passant l'id de la catégorie en variable GET.

De là, tu vérifies si cette variable est pésente dans l'url, si oui, tu sélectionnes dans ta table les sous-catégories dans ta table et tu les affiches lors de ta boucle.

Eléphant du PHP | 153 Messages

30 août 2006, 14:14

Merci spirou :D

Je développe ça et je dirais ce qu'il en est. :wink:

Eléphant du PHP | 153 Messages

30 août 2006, 16:46

bien :)

je n'arrive pas à afficher les sous-catégories en même temps que la catégorie cliquée, de cette manière :

|------ Cat A
|-- SousCat A1
|-- SousCat A2
|-- SousCat A3
|------ Cat B
|------ Cat C
|------ Cat D

J'arrive à afficher toutes les catégories, je clique, j'affiche uniquement les sous-catégories correspondant à la catégorie cliquée.

Il doit y a voir une astuce que je ne saisie pas :?

Eléphant du PHP | 172 Messages

30 août 2006, 17:11

Tu as 2 tables ?
Une des catégories, et une des sous-catégories ?

Eléphant du PHP | 153 Messages

30 août 2006, 17:21

non non, une seule table.

Avatar du membre
ViPHP
ViPHP | 3008 Messages

30 août 2006, 21:21

Avec une table je crains que ce ne soit pas possible. Il t'en faut au moins deux pour faire les jointures et afficher comme tu l'espères.

ViPHP
ViPHP | 2144 Messages

30 août 2006, 21:23

Avec une table je crains que ce ne soit pas possible. Il t'en faut au moins deux pour faire les jointures et afficher comme tu l'espères.
Avec mysql, il doit être possible de n'avoir qu'une seule table, mais de la dédoubler en utilisant des alias différentes du genre :

Code : Tout sélectionner

select t1.libelle, t2.libelle from table t1, table t2 where t1.id = t2.idParent
Evidement ce n'est valable que pour un nombre limité et connu d'avance de niveaux.

A vérifier quand même...

Eléphant du PHP | 197 Messages

31 août 2006, 00:10

j'ai dévellopé un QCM sur ce schéma, c'est interessant niveau execution (moins de requetes à faire).

Mais niveau prog c'est vachement plus dùr (il faut utiliser des fonctions récursives)

mais si tu n'as pas l'habitude, utilises plutot plusieurs tables...

Eléphant du PHP | 337 Messages

31 août 2006, 03:38

Avec une seule table, tu peux ajouter un champ qui représente non seulement la profondeur de menu mais aussi l'id du menu "père" d'un sous-menu, si c'en est un.

Mettons que ce champ se nomme "categorie_profondeur", et soit de type INT(11), comme ton champ categorie_id. Si c'est un menu "père", il a pour valeur "categorie_profondeur=0", sinon il a pour valeur "id du menu père".

Quand tu veux générer ton menu, tu ferais alors une requête du genre :

$sql = "SELECT categorie_id,categorie_nom FROM table_menu WHERE categorie_profondeur='0' ORDER BY categorie_nom ASC";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
    // On affiche ce menu père
    echo $row['categorie_nom']."<br />";

    // On affiche les éventuels menus fils qu'il y a
    $sql2 = "SELECT categorie_nom FROM table_menu WHERE categorie_profondeur='".$row['categorie_id']."' ORDER BY categorie_nom ASC";
    $result2 = mysql_query($sql2);
    while($row2 = mysql_fetch_array($result2))
    {
        echo $row2['categorie_nom']."<br />";
    }
}
Eeeuh voilà, à peu de choses près ça devrait marcher. Par contre je ne suis pas assez calé en php/mysql pour savoir quelle solution serait la plus efficace : 2 tables croisées ou une seule avec requêtes imbriquées.

En ajoutant 2 champs au lieu d'un seul (un pour la profondeur, et l'autre pour l'id du menu père) tu peux même faire des menus / sous-menus / sous-sous-menu / etc. à l'infini.

ViPHP
ViPHP | 2144 Messages

31 août 2006, 09:30

Si le menu, n'a que deux niveau, comme dans l'exemple donné dans le premier message, la solution que j'ai donnée devrait marché. Dans la mesure, où j'imagine que ce menu sera dans toutes les pages du site, je crains que réaliser plusieurs select sur la base de donnée, dans un while, risque d'être assez lourd, si le menu contient plusieurs item.

Eléphant du PHP | 153 Messages

31 août 2006, 15:07

Me revoila. :D

Bien, j'ai adapté le script de finipe. Le problème, c'est que j'ai l'ensemble des catégories et des sous catégories qui s'affichent, par contre, dans le bon ordre, je m'explique :

Voici l'affichage que j'obtiens, au 1er affichage :

------| Cat A <----- Catégorie principale
-- Cat A1 <----- Sous-Cat de A
-- Cat A2 <----- Sous-Cat de A
-- Cat A3 <----- Sous-Cat de A
------| Cat B <----- Catégorie principale
-- Cat B1 <----- Sous-Cat de B
-- Cat B2 <----- Sous-Cat de B
------| Cat C <----- Catégorie principale
------| Cat D <----- Catégorie principale

Alors que j'aimerais avoir :

Menu normal (1er affichage).
|------Cat A <--- catégorie parincipale
|------Cat B <--- catégorie parincipale
|------Cat C <--- catégorie parincipale
|------Cat D <--- catégorie parincipale


On clique sur une cat. principale (ex : A), affichage des sous-catégories correspondantes.
|------Cat A
--Cat A1 <--- sous-catégories
--Cat A2
--Cat A3
--Cat A4
|------Cat B
|------Cat C
|------Cat D


On clique sur une autre cat. principale (ex : C), affichage des sous-catégories correspondant à celle-ci.
|------Cat A
|------Cat B
|------Cat C
--Cat C1 <--- sous-catégories
--Cat C2
--Cat C3
--Cat C4
|------Cat D

Je précise que je n'ai qu'une seule profondeur (une sous-catégories).

Je vous remercie pour votre aide, passée et futur :D

ViPHP
ViPHP | 2144 Messages

31 août 2006, 16:17

ça va être vite très lourd à gérer, surtout pour le serveur de base de donnée, qui va recevoir un paquet de requêttes...
c'est toi qui voit, mais pourquoi ne pas tout obtenir avec un seul select (et un seul while) sans compter que pour même pour les catégories sans sous-catégories, tu vas lancer un select, qui ne récupérera aucune sous catégorie, mais aura quand même fait tourner le serveur pour rien.

Avec ceci, tu dois obtenir ce que tu veux:
$req = mysql_query("select t1.libelle as cat, t2.libelle as sousCat from table t1, table t2 where t1.id = t2.idParent") or die(mysql_error());

$cat ="";
while($resultat = mysql_fetch_array($req)){
 if ($cat != $resultat['cat']){
   print $resultat['cat'];
   $cat = $resultat['cat'];
}
print $resultat['sousCat'];

}
Quand gêrer l'apparition des sous-catégorie en fonction, de clique, il vaudrait vraiement mieux, gêrer ça en CSS et/ou JavaScript, pour éviter de surcharger un peu plus le serveur de base de donnée.

Eléphant du PHP | 153 Messages

31 août 2006, 17:02

merci iclo, je pars comme ça et ça fonctionne très bien :D

Par contre, si je rajoute une profondeur de sous-catégorie, je dois rajouter quelque chose dans la requête ?

Merci.

ViPHP
ViPHP | 2144 Messages

31 août 2006, 17:24

Tu rajoutes un troisième alias sur la même table, avec une condition de jointure en plus:

Code : Tout sélectionner

select t1.libelle as cat, t2.libelle as sousCat, t3.libelle as sousSousCat from table t1, table t2, table t3 where t1.id = t2.idParent and t2.id = t3.idParent
Et bien-sûr, il faut gêrer ce niveau supplémentaire dans le code, en utilisant le même principe qu'avec deux niveaux, c'est un peu plus compliqué, mais ça reste réalisable.