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

Résolu
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007 - 9 sept. 2007 à 22:13
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007 - 10 sept. 2007 à 21:32
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

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
10 sept. 2007 à 19:28
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
3
coockiesch Messages postés 2268 Date d'inscription mercredi 27 novembre 2002 Statut Membre Dernière intervention 13 septembre 2013 4
9 sept. 2007 à 22:51
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???"
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
9 sept. 2007 à 22:59
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) ; " :-(...
0
coockiesch Messages postés 2268 Date d'inscription mercredi 27 novembre 2002 Statut Membre Dernière intervention 13 septembre 2013 4
9 sept. 2007 à 23:06
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???"
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
9 sept. 2007 à 23:16
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 :- ?
0
coockiesch Messages postés 2268 Date d'inscription mercredi 27 novembre 2002 Statut Membre Dernière intervention 13 septembre 2013 4
9 sept. 2007 à 23:19
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???"
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
9 sept. 2007 à 23:32
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.
0
coockiesch Messages postés 2268 Date d'inscription mercredi 27 novembre 2002 Statut Membre Dernière intervention 13 septembre 2013 4
9 sept. 2007 à 23:33
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???"
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
9 sept. 2007 à 23:36
Merci, et bonne nuit ;-) !
0
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
10 sept. 2007 à 06:33
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
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
10 sept. 2007 à 07:21
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 ?
0
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
10 sept. 2007 à 07:49
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
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
10 sept. 2007 à 16:05
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 :).
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
10 sept. 2007 à 20:45
MERCI COUCOU747 :-))) !!! Merci Merci Merci :-) !!!!
0
Evangun Messages postés 1980 Date d'inscription dimanche 20 février 2005 Statut Membre Dernière intervention 24 septembre 2012 4
10 sept. 2007 à 21:19
Hello, tu peux aussi accepter sa réponse :)
0
yazerty55 Messages postés 13 Date d'inscription vendredi 7 septembre 2007 Statut Membre Dernière intervention 17 septembre 2007
10 sept. 2007 à 21:32
Ah ui, désolé je suis nouveau sur ce forum ;-).
 Pratique !
0
Rejoignez-nous