Recréer une arborescence à partir d'une source BDD

Eléphanteau du PHP | 15 Messages

21 avr. 2009, 15:34

Salut tout le monde,
J'ai une formidable table MySQL. Dedans 3 champs :
  • id
    id_parent
    toto_name
Pour comprendre : il y a un toto parent, qui a des toto fils, qui ont des toto fils ... Un bel arbre avec des x branches.
Je veux recréer cet arbre dans le genre :
-toto
|-toto1
-|-toto10
--|-toto101
--|-toto102
-|-toto11
|-toto2
|-toto3
-|-toto31
-|-toto32
...

j'ai fait ca :
echo "<table>";

$SQL = "SELECT id,toto_name FROM table";
$REQ = @mysql_query($SQL, $mysqlCnx) or die('Pb de requête 1');

while ($Res = mysql_fetch_array($REQ,  MYSQL_ASSOC)) {
	
	echo "<tr><td>".$Res['toto_name']."</td><td>";
	echo "<table>";
	$test=array($Res['id']);
	
	foreach($test as $id)
	{
		
		$SQL2 = "SELECT id,toto_name FROM table WHERE id_parent = '$id'";
		$REQ2 = @mysql_query($SQL2, $mysqlCnx) or die('Pb de requête 2');
		
		while ($Res2 = mysql_fetch_array($REQ2,  MYSQL_ASSOC)) {
			echo "<tr><td>".$Res2['toto_name']."</td></tr>";
		}
		
		echo "</table></td></tr>";
	}
}
echo "</table>";
Et ce fabuleux script de m... ne me donne que le premier niveau de branche.

Une idée pour arriver à une arborécence complète et sans me taper dans le code à chaque fois une requete SQL pour chaque niveau de branche ???
Julien
------

ViPHP
ViPHP | 3300 Messages

21 avr. 2009, 18:51

je te conseille de te faire une fonction récursive qui en gros prend en argument un id pere, et construit le résultat pour les id fils, tout en s'appelant elle même pour construire les fils des fils, et indéfiniment.
Fait du php depuis que ca existe ou presque :)

Mammouth du PHP | 661 Messages

21 avr. 2009, 19:02

je suppose que si il n'y a pas de parent, tu as en identifiant parent null ou 0

je vais considérer que c'est nul, et vais il donner 0 dans la conception de la table ::

$SQL = "SELECT * FROM table";
$REQ = @mysql_query($SQL, $mysqlCnx) or die('Pb de requête 1');

$Arbre = array();
while ($Res = mysql_fetch_array($REQ,  MYSQL_ASSOC)) {
  $parent = (!empty($Res['parent']) && ! is_null($Res['parent'])) ? $Res['parent'] : 0 ;
  if(empty($Arbre[$parent]) $Arbre[$parent] = array();
  $Arbre[$parent][count($Arbre[$parent])] = $Res;
}

/* désormé, nous avons une table de la forme :

$Arbre[id_parent] = array( [enfant1], [enfant2], ...);

nous allons donc monter une fonction pour l'utilisation de nos éléments : */

function extra($arr, $Arbre){
  print_r($arr);
  if (isset($Arbre[$arr['id']]){
    foreach($Arbre[$arr['id']] as $ar){
      extra($ar, $Arbre);
    }
  }
}

// comme tu le constate la fonction s'appelle elle-meme si il existe des enfant portant son identifiant
// il ne nous reste plus qu'à lancer la fonction pour tous les parents dont l'iedentifiant est '0'

  if (isset($Arbre[$arr[0]]){
    foreach($Arbre[$arr[0]] as $ar){
      extra($ar, $Arbre);
    }
  }
// et voila ;)

mais ce serait beaucoup plus simple avec une class surtout que cela éviterais de transporter $Arbre, ...

@+

Eléphanteau du PHP | 15 Messages

22 avr. 2009, 12:17

Tout d'abord. Merci pour les commentaires. Ca m'a permis de comprendre pas mal de choses.

J'ai corrigé qq erreurs de syntaxe, car chez moi, il n'y avait pas de return.
Mais le problème, c'est que la page malgré qu'elle soit envoyée à mon navigateur, pas de données ! ARF...
Petite chose, me suis aperçu que 'parent' était une fonction PHP, alors je l'ai transformée en 'parente'

Voici le code que j'ai (commenté)
$SQL = "SELECT * FROM service WHERE activate = '1'";
$REQ = @mysql_query($SQL, $mysqlCnx) or die('Pb de requête 1');

$Arbre = array();
while ($Res = mysql_fetch_array($REQ,  MYSQL_ASSOC)) {
  $parente = (!empty($Res['service_parent']) && ! is_null($Res['service_parent'])) ? $Res['service_parent'] : 1 ;
  if(empty($Arbre[$parente])[b])[/b] $Arbre[$parente] = array(); // Manquait la parenthèse fermée
  $Arbre[$parente][count($Arbre[$parente])] = $Res;
}

/* désormé, nous avons une table de la forme :

$Arbre[id_parent] = array( [enfant1], [enfant2], ...);

nous allons donc monter une fonction pour l'utilisation de nos éléments : */

function extra($arr, $Arbre){
  print_r($arr);
  if (isset($Arbre[$arr['service_id']])){
    foreach($Arbre[$arr['service_id']] as $ar){
      extra($ar, $Arbre);
    }
  }
}

// comme tu le constate la fonction s'appelle elle-meme si il existe des enfant portant son identifiant
// il ne nous reste plus qu'à lancer la fonction pour tous les parents dont l'identifiant est '0' 
////// En fait mon premier id est 1, j'ai donc mis $arr[1]
  if (isset($Arbre[$arr[1]])){
    foreach($Arbre[$arr[1]] as $ar){
      extra($ar, $Arbre);
    }
  }
As-tu une idée pourquoi j'ai rien en retour ?

Petite question annexe : Si je veux afficher d'autres colonne de ma table, je le code dans la fonction ? ou je refais une requete SQL que je met après le extra($ar, $Arbre); de la fin ?

ViPHP
ViPHP | 4674 Messages

23 avr. 2009, 10:57

Hey :-),

Je n'ai lu le sujet qu'en diagonal mais quand je vois : « base de données », « relationnel » et « arborescence », ça fait tilt et je pense : arbre intervallaire.
Va jeter un œil sur Google, tu y trouveras ton bonheur ;-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 94 Messages

23 avr. 2009, 12:12

Une fonction récursive pour gérer une arborescence :
http://www.coinduwebmaster.com/menu-arb ... ve-php/89/

C'est vrai que les arbres intervallaires ont l'air de permettre une approche différente.
Je ne connais pas, je vais tester ça :D

Eléphanteau du PHP | 15 Messages

24 avr. 2009, 14:21

Ca c'est une super piste.
Je teste et vous dit
Julien
------