Recherche sur la branche d'un thesaurus hiérachique

cs_oceanrider Messages postés 13 Date d'inscription jeudi 18 novembre 2004 Statut Membre Dernière intervention 20 juillet 2011 - 30 mars 2006 à 19:09
cs_oceanrider Messages postés 13 Date d'inscription jeudi 18 novembre 2004 Statut Membre Dernière intervention 20 juillet 2011 - 3 sept. 2006 à 21:58
Bonjour,

N'ayant une fois de plus pas pu trouver de réponse, je vous fais part de mon problème :
Je dispose d'une vidéothèque dans lesquels sont répertoriés mes films ainsi que ceux de mes amis. Chaque film peut être classé selon une liste d'autorité hiérarchisée.
ex. :
1 0 film
2 1 horreur, fantastique, SF
3 2 science-fiction
4 2 fantastique
5 2 horreur
6 1 western
7 6 spaghettis
8 6 classiques
9 6 crépusculaires

Tout mon problème est de réussir à effectuer une recherche sur une branche entière (ex. : western) sans pour autant multiplier les requêtes (1 requête sur western puis 1 sur spaghettis, 1 sur classiques, etc.).

Pour l'instant, mon idée était en reprenant le code de Titatou (http://www.phpcs.com/codes/ARBORESCENCE-RECURSIVE_30776.aspx) sur la construction d'un arbre récursif, non pas d'"afficher" la liste des catégories, mais de placer chaque valeur de cette liste dans un tableau ou dans une chaîne, afin de placer ce résultat dans une requête du type :
"SELECT titre,réal,année FROM Films,Categories WHERE idCat=XidCat AND ($critere);"
en remplaçant $critere par "idCategorie=6 OR idCategorie=7 OR idCategorie=8 OR idCategorie=9"

Voici ce que j'ai tenté (sans succès) jusqu'à présent :
function recur($tab,$pere)
{
//ballayage du tableau
for ($x=0;$x<count($tab);$x++)
{
//si un élément a pour père : $pere
if ($tab[$x][1]==$pere)
{
//on stocke la valeur dans un tableau
$liste[]=$tab[$x][0];
//et on recherche ses fils
recur($tab,$tab[$x][0]);
}
}
}

$reqCategories="SELECT idCategorie,idGenerique,categorie FROM Categories";
$resCategories=mysql_query($reqCategories) or die("Une erreur est survenue dans l'éxécution de la requête reqCategories !");
while($ligne=mysql_fetch_array($resCategories,MYSQL_ASSOC))
{
extract($ligne);
$data[] = array($idCategorie,$idGenerique);
}
$liste=recur($data,$formIdCat);

Le problème, c'est que je n'obtiens absolument rien.
Peut avez-vous une suggestion, peut être une toute autre méthode qui conviendrait mieux.

Merci d'avance.

4 réponses

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
30 mars 2006 à 19:50
Salut,

function recur($tab,$pere)
{
//ballayage du tableau
for ($x=0;$x<count($tab);$x++)
{
//si un élément a pour père : $pere
if ($tab[$x][1]==$pere)
{
//on stocke la valeur dans un tableau
$liste[]=$tab[$x][0];
//et on recherche ses fils
recur($tab,$tab[$x][0]);
}
}

//Ta fonction ne renvoi rien, alors évidement...
du coup, liste ne contient rien... utilise soit un & devant les
arguments, soit un return à la fin de ta fonction
}

$reqCategories="SELECT idCategorie,idGenerique,categorie FROM Categories";
$resCategories=mysql_query($reqCategories) or die("Une erreur est survenue dans l'éxécution de la requête reqCategories !".mysql_error()
);
while($ligne=mysql_fetch_array($resCategories,MYSQL_ASSOC))
{
$data[] = array($ligne['idCategorie'],$ligne['idGenerique']);
}
$liste=recur($data,$formIdCat);




In a dream, I saw me, drop dead... U was there, U cried... It was just a dream, if I die, U won't cry, maybe, U'll be happy

Mon site (articles sur la programmation et programmes)
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
30 mars 2006 à 20:04
Hello,

je pige pas là...c'est moi, où tu te complqiues gravement la vie ?
Si 1 film appartient à 1 catégorie :

FILMS
film_id
film_nom
cat_id
...

CATEGORIES
cat_id
cat_libelle
cat_id_mere

requête avec tes catégories, on cherche sur western, cat_id = 6

SELECT
film.film_nom FROM films film, categories cat WHERE cat.cat_id film.cat_id AND (cat.cat_id 6 OR cat.cat_id_mere = 6)

Si un
film peut avoir plusieurs catégories, c'est pareil, mais avec en plus
une table intérmédiaire de correspondance entre films et catégories.
0
cs_oceanrider Messages postés 13 Date d'inscription jeudi 18 novembre 2004 Statut Membre Dernière intervention 20 juillet 2011
31 mars 2006 à 00:50
En réponse à Malalam, effectivement, mais cela limite la recherche à deux niveaux :
ainsi si je recherche tous les films (cat_id=1), je récupère ce qui correspond à "films", "western" et "horreur, SF, fantastique", mais pas ce qui a été classé dans "science-fiction", "fantastique", "horreur", "spaghetti", etc.
En outre, ma hiérarchie peut être plus profonde que dans l'exemple que j'ai donné ici et va jusqu'à 5 niveaux.
Sauf erreur de ma part, je suis donc bien obligé de procéder à une boucle récursive afin d'explorer les sous-niveaux.

Et pour ce qui est de la remarque sur le trés visible mysql_error(), il est effectivement plus sage de l'ajouter (mais pas indispensable).

En tous les cas, voici le code fonctionnel que j'obtiens finalement :

function recur($tab,$pere)
{
$liste=array();
//balayage du tableau
for ($x=0;$x<count($tab);$x++)
{
//si un élément a pour père : $pere
if ($tab[$x][1]==$pere)
{
//on stocke la valeur dans un tableau
$liste[]=$tab[$x][0];
//et on recherche ses fils
recur($tab,$tab[$x][0]);
}
}
//on renvoie la valeur
return $liste;
}

//recherche de toutes les catégories, leur ID et leur générique
$reqCategories="SELECT idCategorie,idGenerique,categorie FROM Categories";
$resCategories=mysql_query($reqCategories) or die("Une erreur est survenue dans l'éxécution de la requête reqCategories !");
while($ligne=mysql_fetch_array($resCategories,MYSQL_ASSOC))
{
extract($ligne);
//construction du tableau contenant toutes les catégories
$data[] = array($idCategorie,$idGenerique);
}
$liste=recur($data,$formIdCat);
//la fonction ne renvoie pas la catégorie séléctionnée, on l'intègre donc dans la valeur appelée plus tard comme critère de recherche
if($liste!="")
{
$critere=$formIdCat.' OR idCategorie='.implode($liste,' OR idCategorie=');
}
else
{
$critere=$formIdCat;
}

//requête finale recherchant les films de la catégorie ou des catégories filles
$reqRechSimp="SELECT idDoc,titre,titreOrig,annee,categorie FROM Documents,Categories WHERE X_idCategorie=idCategorie AND (idCategorie=$critere) ORDER BY $ordre LIMIT $limitDeb,$tailleGroupe";
$result=mysql_query($reqRechSimp) or die("Une erreur est survenue dans l'éxécution de la requête reqRechSimpCat ! ".mysql_error());

Voici la requête obtenue : SELECT
idDoc,titre,titreOrig,annee,categorie FROM Documents,Categories WHERE
X_idCategorie=idCategorie AND (idCategorie=2 OR idCategorie=3 OR idCategorie=4 OR idCategorie=5) ORDER BY titre
LIMIT 0,20

Merci à tous pour vos contributions, en espérant que mes propres déboires pourront en aider certains.
0
cs_oceanrider Messages postés 13 Date d'inscription jeudi 18 novembre 2004 Statut Membre Dernière intervention 20 juillet 2011
3 sept. 2006 à 21:58
Petite mise à jour : en fait, je viens de m'apercevoir que cette fonction n'est pas pleinement opérationnelle.
En effet, avec le return cette fonction ne parvient pas à renvoyer les Id au dela du deuxième niveau de la hiérarchie (elle trouve les spécifiques du terme recherché, mais pas les spécifiques des spécifiques). Aussi je l'ai modifiée de façon à ce qu'elle soit pleinement opérationnelle en remplaçant le return par un passage des arguments par référence.

function recur($tab,$pere,&$valeurs)
    {
    //balayage du tableau
    for ($x=0;$x<count($tab);$x++)
        {
        //si un élément a pour père : $pere
        if ($tab[$x][1]==$pere)
            {
            //on stocke la valeur dans un tableau
            $valeurs[]=$tab[$x][0];
            //et on recherche ses fils
            recur($tab,$tab[$x][0],&$valeurs);
            }
        }
    }

//recherche de toutes les catégories, leur ID et leur générique
$reqCategories="SELECT idCategorie,idGenerique,categorie FROM Categories";
$resCategories=mysql_query($reqCategories) or die("Une erreur est survenue dans l'éxécution de la requête reqCategories !".mysql_error());;
while($ligne=mysql_fetch_array($resCategories,MYSQL_ASSOC))
    {
    //construction du tableau contenant toutes les catégories
    $data[] = array($ligne['idCategorie'],$ligne['idGenerique']);
    }
recur($data,$formIdCat,$liste);

Ainsi, $liste est exploitable et contient cette fois tous les termes spécifiques à celui recherché.
0
Rejoignez-nous