Bonjour,
J’ai besoin d’aide pour modéliser en PHP et en MySQL (enfin surtout pour la partie MySQL) un système de news.
Il y a bien sûr une table “articles” (id_art, titre, texte, date, …) et une table “categories” (id_cat, nom).
Il faut donc également une table “lien_art_cat” faisant le lien entre un article et sa/ses catégorie(s) associée(s) (id_art, id_cat).
Un article peut avoir plusieurs catégories.
Une catégorie peut être fille d’une autre catégorie.
La modélisation doit pouvoir permettre de vérifier simplement si deux catégories, choisie par l’utilisateur lors de l’ajout d’un article, ne sont pas imbriquées l’une dans l’autre. Exemple : “Composants > Processeurs” et “Composants > Processeurs > AMD > Athlon”, dans ce cas là, la catégorie “Composants > Processeurs” doit être ignorée (car déjà comprise dans “Composants > Processeurs > AMD > Athlon”).
Il faut aussi pouvoir sélectionner ("SELECT … " en MySQL) simplement toutes les catégories enfants d’une catégorie donnée (utile pour trouver tous les articles traitant des “Composants” par exemple c’est à dire : “Composants > Processeurs”, “Composants > Processeurs > Intel”, “Composants > Processeurs > AMD”, “Composants > RAM”, “Composants > Cartes Graphiques”, … (récursif en profondeur donc))
Population de la table catégorie :
- Composants (ID : 5)
- Périphériques (ID : 2)
- Processeurs (ID : 7)
- Jeux Vidéos (ID : 9)
- Intel (ID : 12)
- Athlon (ID : 43)
- AMD (ID : 1)Concepts/nomenclature :
Catégorie parente : Catégorie se trouvant immédiatement au dessus d’une catégorie (qui est donc sa fille) dans la hiérarchie.
Catégorie racine : Catégorie n’ayant pas de catégorie parente (Composants, Périphériques, Jeux Vidéos, etc.). Ce type de catégorie créer une branche à laquelle vont appartenir toutes les catégorie filles (et petites-filles et petites-petites-filles, etc.) de cette catégorie racine.
Génération : distance entre une catégorie et la catégorie racine de sa branche (une sorte d’age). Une catégorie racine à donc une génération de 0.
Pour cela, j’avais songé à deux façons de faire :
Première façon :
Je me rends compte que pour la vérification, une comparaison du “chemin” de la catégorie serait le plus simple : si on trouve le chemin d’une catégorie au début du chemin d’une autre, alors la première catégorie peut être ignorée.
Exemple :
Le chemin de la catégorie “Composants > Processeurs” ($cat1) serait “5.7” ($chemin1) et celui de “Composants > Processeurs > AMD > Athlon” ($cat2) serait “5.7.1.43” ($chemin2).
Donc pour faire la vérification :[quote=""]
Trier les 2 chemins par génération croissante : compter le nombre de point dans le chemin.
si la chaîne $chemin1 se trouve dans la chaîne $chemin2 à la position 0 alors ignorer $cat1 finsi
[/quote]
Il suffirait d’ajouter un simple champ dans la table catégorie qui contiendrait le chemin de la catégorie.
Pour la sélection des articles d’une catégorie donnée (par exemple"Composants > Processeurs" de chemin “5.7”), la requête suivante devrait suffire :
SELECT id_art, titre, texte, date
FROM articles A, categories C, lien_art_cat L
WHERE
C.chemin LIKE "5.7%" AND // On ne récupère que les catégories dont le chemin débute par "5.7", soit toutes les catégories filles de la catégorie 5.7
L.id_cat = C.id_cat AND
A.id_art = L.id_art
A l’usage (affichage de toutes les catégories, avec la hiérarchie, dans un menu déroulant par exemple), je me demande si le fait que les chemins soient codés un peu bizarrement (pas de taille fixe pour les identifiant de catégorie, séparateur de niveau intégré, etc.) ne soit pas un problème ?
Deuxième façon :
Dans la table catégories, rajouter les champs “id_parente” (donne l’id_cat de la catégorie parente, NULL si pas de catégorie parente), id_cat_racine (donne l’id_cat de la catégorie racine de la branche) et generation (utile pour savoir rapidement si deux catégories sont soeurs).
Ainsi la vérification des deux catégories imbriquées se ferait ainsi :[quote=""]
Trier les 2 catégories par génération croissante.
si $cat1 est un ancêtre de $cat2 alors ignorer $cat1 finsi
[/quote]
Mais je ne vois pas comment trouver simplement si une catégorie est ancêtre d’une autre.
Pour la sélection : je ne vois pas de requête simple pour sortir tous les id_cat des catégories descendant d’une catégorie donnée.
Par contre, je pense que la génération d’un arbre hiérarchique ne devrait pas être un soucis avec cette solution (je pense).
Il y a sûrement une autre solution que les deux que j’ai envisagé (en plus de la solution “Obiwan Kenobi” :D)
Edit : Correction des fautes