Fonction récursive et enregistrement ds tableau[ ] :-/ ? [Résolu]

Signaler
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007
-
yazerty55
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007
-
Bonjour,

J'ai une table mysql avec ceci :

category_id - category - parent_num
1 - Catégorie 1 - 0
2 - Catégorie 2 - 5
3 - Catégorie 3 - 2
4 - Catégorie 4 - 3
5 - Catégorie 5 - 3
...


Il s'agit d'un système de catégorie à plusieurs niveaux. Une catégorie peut en contenir une autre (ceci à l'infini). Si je suis dans la catégorie 5 le fil d'ariane peut ainsi donner :

Index > Catégorie 3 > Catégorie 5 >Catégorie 2

Je souhaite donc faire un fil d'ariane. J'ai abouti à cette fonction :

// Fil d'Ariane
$category_id = $db_data['category_id'];
echo $category_id; // affiche bien l'id de la catégorie en cours

function getTopParent($pi_current, $pa_data)
        {

            // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());

            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                $pa_data = array($aData);
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

        // Appel de la function
        getTopParent($category_id, $pa_data) ;
       
        // Reverse l'ordre des resultats pour avoir en premier le root
        $aFinalData = array_reverse($pa_data) ; 

// pour parcourir ce tableau, utilisons la boucle foreach
foreach($individu as $cle=>$valeur)
    {
    echo $cle.' : '.$valeur.'
';
    } 


Mais cela me sort ce message d'erreur :

Warning: array_reverse() [function.array-reverse]: The argument should be an array

pour la ligne correspondant à :

$aFinalData = array_reverse($pa_data) ;


Le problème semble venir de (la mauvaise) insertion des données dans le tableau, car lorsque je fais seulement:

function getTopParent($pi_current, $pa_data)
        {

            // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());

            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                echo $aData['category'];
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

        // Appel de la function
        getTopParent($category_id, $pa_data) ;


Cela m'affiche bien le nom de mes catégories, mais dans l'ordre inverse d'un fil d'ariane (à gauche il y a la catégorie la plus basse dans la hiérarchie et à droite la plus haute, alors que ça devrait bien sûr être l'inverse pour un fil d'ariane...). D'où l'idée de stocker les données dans un tableau pour ensuite inverser le tableau et afficher les données (si vous avez mieux je suis tout autant preneur :) ).

J'ai cherché avec mon ami Google les cours présentant la mise en tableau de données, mais je n'ai pas réussi à comprendre où était l'erreur dans mon code :-/... Je suppose pourtant que la bêtise est évidente :- ?

Pourriez-vous m'aider s'il vous plait :- ?

16 réponses

Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
30
Salut

function getTopParent($pi_current, &$pa_data)
        {
             // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());
 
            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                $pa_data[]=$aData;
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

apres avoir fait ton appel de fonction

foreach ($tableau as $a){
echo $a['...'].' =>'.$a['...'];
}

<hr />une recherche sur exalead vous aurait peut-etre evite de poser cette question

In a dream, I saw me, drop dead...
U were there, U cried...
It was just a dream,
if I die, U won't cry, maybe, U'll be happy
Messages postés
2268
Date d'inscription
mercredi 27 novembre 2002
Statut
Membre
Dernière intervention
13 septembre 2013
3
Salut!
 Il y a qqch que je comprend pas: mysql_fetch_assoc te renvoie un tableau... Pourquoi créer un autre tableau (à un seul indice) contenant ce tableau?

Ne pourrais tu pas juste faire:
$pa_data = mysql_fetch_assoc($req);
getTopParent($aData['parent_num'], $pa_data);

@++

R@f

La boîte à bouts de codes
"On dit que seulement 10 personnes au monde comprenaient Einstein. Personne ne me comprends. Suis-je un génie???"
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Bonsoir,

Merci pour ta suggestion coockiesch !
Malheureusement si je fais :

            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_array($req);
                $pa_data = mysql_fetch_assoc($req);
                getTopParent($aData['parent_num'], $pa_data);
            }

Ca me renvoit toujours l'erreur " Warning : array_reverse() [function.array-reverse]: The argument should be an array" sur la ligne "$aFinalData = array_reverse($pa_data) ; " :-(...
Messages postés
2268
Date d'inscription
mercredi 27 novembre 2002
Statut
Membre
Dernière intervention
13 septembre 2013
3
Je comprend pas: mysql_fetch_assoc te renvoie un tableau, pouquoi tu veux absolument le bidouiller?
$pa_data = mysql_fetch_assoc($req);
getTopParent($pa_data, $pa_data);

Pcq, si tu fais:
getTopParent($aData['parent_num'], $pa_data);
$aData est un tableau, mais pas $aData['parent_num']....

@++

R@f

La boîte à bouts de codes
"On dit que seulement 10 personnes au monde comprenaient Einstein. Personne ne me comprends. Suis-je un génie???"
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Je ne suis pas sûr de comprendre quelle forme finale tu suggères je crois (désolé :-/). Pourrais-tu remettre la partie du

if (mysql_num_rows($req)>0)
            {
            }

telle que tu me suggère afin que j'y vois plus clair dans la démarche s'il te plait :- ?
Messages postés
2268
Date d'inscription
mercredi 27 novembre 2002
Statut
Membre
Dernière intervention
13 septembre 2013
3
Ca?
if (mysql_num_rows($req)>0)
      {
                $aData = mysql_fetch_assoc($req);
                getTopParent($aData['parent_num'], $aData);
            }

@++

R@f

La boîte à bouts de codes
"On dit que seulement 10 personnes au monde comprenaient Einstein. Personne ne me comprends. Suis-je un génie???"
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Merci pour ton aide !

Mmm' alors non ça ne marche pas non plus quand je fais ça :-( :

------------------
// Fil d'Ariane
$category_id = $db_data['category_id'];
echo $category_id; // affiche bien l'id de la catégorie en cours
 
function getTopParent($pi_current, $pa_data)
        {
 
            // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());
 
            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                echo $aData['parent_num']; // Affiche bien les id des catégories parentes de celles qui doivent s'afficher
                getTopParent($aData['parent_num'], $aData);
            }
        }
 
        // Appel de la function
        getTopParent($category_id, $aData) ;
      
        // Reverse l'ordre des resultats pour avoir en premier le root
        $aFinalData = array_reverse($aData) ;
 
// pour parcourir ce tableau, utilisons la boucle foreach
foreach($individu as $cle=>$valeur)
    {
    echo $cle.' : '.$valeur.'
';
    }
------------------
(j'ai mis $aData à la place de pa_Data du coup pour la suite du code).

ps : par contre je crois que je vois ce que tu m'explique avec le tableau qu'il ne sert à rien de recréer puisque mysql_fetch_assoc en crée un lui-même.
Messages postés
2268
Date d'inscription
mercredi 27 novembre 2002
Statut
Membre
Dernière intervention
13 septembre 2013
3
J'y réfléchis et je te redis demain, si c'est pas réglé par qlqn d'autre d'ici là!...

@++

R@f

La boîte à bouts de codes
"On dit que seulement 10 personnes au monde comprenaient Einstein. Personne ne me comprends. Suis-je un génie???"
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Merci, et bonne nuit ;-) !
Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
30
Salut

ta fonction ne renvoie rien... faut alors passer ce param par reference, ce qui implique de le declarer plus tot...

function getTopParent($pi_current, &$pa_data)
        {
 
            // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());
 
            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                $pa_data[]=$aData['parent_num'];
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

tu l'appelles en faisant :

$aData=array();
        // Appel de la function
        getTopParent($category_id, $aData) ;
      
        // Reverse l'ordre des resultats pour avoir en premier le root
        $aFinalData = array_reverse($aData) ;
 
// pour parcourir ce tableau, utilisons la boucle foreach
foreach($individu as $cle=>$valeur)
    {
    echo $cle.' : '.$valeur.'
';
    }

sinon, si tu utilises mysql5, tu peux peut-etre utiliser une fonction sql...

CREATE FUNCTION menu_deroule(id INT UNSIGNED)
RETURNS TEXT DETERMINISTIC
BEGIN
  DECLARE t TEXT;
  DECLARE r TEXT;
  DECLARE i INT UNSIGNED;
  SET i = id;
  SET t = "";
  SET r = "";
  WHILE i!=0 AND ISNULL(i)=0
  DO
    SELECT `child_of`, `titre` INTO i, t FROM `menu` WHERE menu.id=i;
    SET r = CONCAT(t, "/", r);
    IF i = id THEN
      SET i=0;
    END IF;
  END WHILE;
  RETURN r;
END;

pour ma fonction, j'avais une table :
id           child_of               titre
et je recuperais les titres separes par des /

<hr />une recherche sur exalead vous aurait peut-etre evite de poser cette question

In a dream, I saw me, drop dead...
U were there, U cried...
It was just a dream,
if I die, U won't cry, maybe, U'll be happy
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Merci beaucoup coucou747 : ça marche !! Je me réveille de très bonne humeur grâce à toi :-).
Par contre je ne comprends pas la logique du foreach dans ce cadre là. Je ne vois pas comment faire correspondre les valeurs que je dois utiliser ensemble.
En effet sur mon fil d'ariane je vais bien sûr faire des liens vers chacun des item du fil. Les liens sont constitués de l'id de la catégorie.

Cependant en exécutant ce code php :
            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                $pa_data[]=$aData['category'];
                $pa_data[]=$aData['parent_num'];
               
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

$aData=array();
// Appel de la function
getTopParent($parent_num, $aData) ;
     
// Reverse l'ordre des resultats pour avoir en premier le root
$aFinalData = array_reverse($aData) ;

 foreach($aFinalData as $cle=>$valeur)
    {
    echo $cle.' : '.$valeur.'
';
    }

J'obtiens à l'affichage :
0 : 0
1 : Loisirs & divertissement
2 : 16
3 : Sport
4 : 22
5 : Rugby

La catégorie "Loisirs" porte l'id 16 et "Sport" l'id 22. Je connais l'id de "Rugby", c'est celui de la catégorie en cours.
Il me faut donc cet id lorsque j'affiche "Loisirs" et "Sport" (mais cela peut être pour plus de niveaux, il n'y a pas de limite). Je ne comprends pas comment faire pour avoir la valeur de la boucle suivante pour faire mon lien sur le nom de la catégorie ?
Messages postés
12303
Date d'inscription
mardi 10 février 2004
Statut
Modérateur
Dernière intervention
30 juillet 2012
30
Salut
remplace :
                $pa_data[]=$aData['category'];
                $pa_data[]=$aData['parent_num'];
par
                $pa_data[$aData['parent_num']]=$aData['category'];

et regarde bien ma requete sql, elle peut te permettre de ne faire qu'une requete, et de gagner en temps de generation de ta page...
<hr />une recherche sur exalead vous aurait peut-etre evite de poser cette question

In a dream, I saw me, drop dead...
U were there, U cried...
It was just a dream,
if I die, U won't cry, maybe, U'll be happy
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Ca ne me rentre par le numéro de la catégorie dans la "$cle" bizarrement avec :

function getTopParent($pi_current, &$pa_data)
        {
             // sql + query
            $sSql = "SELECT parent_num, category FROM categories WHERE category_id=$pi_current";
            $req = mysql_query($sSql) or die(mysql_error());
 
            if (mysql_num_rows($req)>0)
            {
                $aData = mysql_fetch_assoc($req);
                $pa_data[$aData['parent_num']]=$aData['category'];
                getTopParent($aData['parent_num'], $pa_data);
            }
        }

$aData=array();
// Appel de la function
getTopParent($parent_num, $aData) ;
     
// Reverse l'ordre des resultats pour avoir en premier le root
$aFinalData = array_reverse($aData) ;
   
    {
    echo $cle.' : '.$valeur.'
';
    }

Ca affiche :
0 : Loisirs & divertissement
1 : Sport
2 : Rugby

J'ai essayé en faisant $pa_data[$pi_current]=$aData['category']; (cf requête SQL) mais cela ne donne rien (le résultat est le même).
Mais je ne comprends pas pourquoi on inverse aData et pas padata dans la suite du code :-? Mais si on inverse pa_data ça rend une erreur (array_reverse() : The argument should be an array
Est-ce bon de ce côté là :-?
ps : pour la fonction Mysql j'ai une base Mysql 5.0 (1&1 en mutualisé). Je regarderais les fonctions Mysql et verrai si je change de stratégie, mais pour le moment cela me parait un peu complexe à la vue de mon niveau actuel (de plus l'aide sur internet sur ce genre de fonction est moins présente que les cours de php :). Mais merci de me signaler qu'il y a plus efficace et performant :) (au pire je mettrai en place un système de cache sur mes pages :).
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

MERCI COUCOU747 :-))) !!! Merci Merci Merci :-) !!!!
Messages postés
1980
Date d'inscription
dimanche 20 février 2005
Statut
Membre
Dernière intervention
24 septembre 2012
5
Hello, tu peux aussi accepter sa réponse :)
Messages postés
13
Date d'inscription
vendredi 7 septembre 2007
Statut
Membre
Dernière intervention
17 septembre 2007

Ah ui, désolé je suis nouveau sur ce forum ;-).
 Pratique !