Newsgroup: it.comp.www.php
Titolo: Un loop infinito...

Ciao a tutti!
Ho una situazione da cui non riesco ad uscire:
Una tabella pgsql in cui ho questi dati
codice | nome  | figli | padre
-------+-------+-------+------
1      | pippo | t     | 0
2      | palla | f     | 0
3      | tizio | t     | 1
4      | gigi  | t     | 3
5      | gianni| f     | 1
dovrebbe farmi generare questo js:
Menu1     = 'pippo'
Menu1_1   = 'tizio'
Menu1_1_1 = 'gigi'
Menu1_2   = 'gianni'
Menu2     = 'palla'
In pratica 'figli' indica se ci sono delle
sottosezioni, e 'padre' indica invece l'eventuale
appartenenza ad una sezione.
Dovrei generare una funzione che chiami sé stessa
finché tutto il menu js non è generato, poiché
non posso sapere a priori quanti livelli ci sono.
Una cosa del genere la feci già in perl, ma ora
non trovo più il codice che scrissi né mi ricordo
come l'ho fatta... qualcuno potrebbe darmi una
mano? Riferimenti e URL sono graditissimi :-)
Grazie,
ValeRyo
--
Valerio Granato
http://www.musicoff.com
 - Music Online For Free
La Grande Comunità Online per Musicisti

2      | palla | f     | 0
	list($codice, $nome, $figli, $padre) = each($riga);
Quando $padre e' diverso da $precedente_padre, sai che il gruppo
di tutti gli elementi con padre $padre e' chiuso e puoi metterlo
in freezer in attesa che l'elemento $padre si presenti:
	$freezer[$padre][] = $lista_righe;
	$lista_righe = array(
		'codice'	=> $codice,
		'nome'		=> $nome,
	);
	$precedente_padre = $padre;
$freezer non e' altro che uno stack (ricorsivo == iterativo piu'
stack, come mi ripeteva il prof. Soda (sempre sia lodato))
Quando arriva il padre, con il suo $codice,
	$nodo = array(
		'codice'	=> $codice,
		'nome'		=> $nome,
	);
	if (isset($freezer[$codice]))
	{
		if ($figli)
		{
			// $freezer[$codice] e' un array di array
			$nodo['sons'] = $freezer[$codice];
			unset($freezer[$codice]);
		}
		else
		{
			// Anomalia: nel DB ci sono figli ma
			// il padre li disconosce.
		}
	}
	else
	{
		// Anomalia: il padre sostiene di avere figli
		// ma nel DB non ci sono.
	}
Alla fine della fiera immetti un falso codice 0, che sara' poi la
radice dell'albero.
Cosi' hai
	$albero = array(
		'codice'	=> 0,
		'nome'		=> 'radice',
		'sons'		=> array
		(
			0	=> array(
				'codice'	=> 1,
				'nome'		=> 'pippo',
				'sons'		=> array(
					0	=> array(
						'codice'	=> 3,
						'nome'		=> 'tizio',
						'sons'		=> array(
							0	=> array(
								'codice'
=> 4,
								'nome'
=> 'gigi',
								'sons'
=> array(
								// Vuoto.
								),
							),
						),
					),
				),
			),
			1	=> array(
				'codice'	=> 2,
				'nome'		=> 'palla',
				'sons'		=> array(
				// Vuoto.
			),
		),
	);
Da questo array poi e' immediato tirare fuori il menu in qualsiasi altra
cosa.
Leonardo
-- 
Time's angles, mages tell, conceal a place
incredible, beyond the mundane mind;
night-shrouded and between the seas of space
dread creatures drift in the ageless winds.

 altra cosa.
:-O non ho parole !
L'idea di ordinarli per padre e girare finché non finisce
un gruppo non mi era venuta proprio, poiché uso una
mia classe per accedere ai DB e nella select_sezioni
non mi è vai servito anche ($orderby) :-(
Grazie mille, quando passi per Napoli avvisami che ti
devo una pizza :-)
Se poi mi viene in mente (o, meglio, ritrovo) il sistema
ricorsivo lo posto qui, magari serve a qualcuno.
Ciao e grazie,


 (Implementazione NON ricorsiva)
Sfruttando la tua idea dell'ordinamento per padre decrescente ho
tirato fuori questo codice, lo posto qui casomai dovesse servire
a qualcuno.
Ovviamente, visto che mi ero fissato per una funzione ricorsiva,
l'ho usata nella stampa del menu :-))
function select_sezioni_array() {
 $risultato = $this->select('codice,sezione,padre,ordine',
  'sezioni', '', 'padre desc, ordine asc');
 foreach ($risultato AS $riga) {
  $stack[$riga[padre]][$riga[codice]] =
   array(
    codice => $riga[codice],
    sezione => $riga[sezione],
    padre => $riga[padre],
    ordine => $riga[ordine]
   );
  if (isset($stack[$riga[codice]])) {
   $stack[$riga[padre]][$riga[codice]][figli] = $stack[$riga[codice]];
   unset($stack[$riga[codice]]);
  }
 }
 return $stack[0];
}
Poi chiamo
function menu_javascript($start,$text,$dim,$array) {
 foreach ($array AS $riga) {
?>
<?=$text?>_<?=$start?>=new Array("<?=addslashes($riga[sezione])?>",
 "URL","", <?=count($riga[figli])?><? if($start == 1) echo ",$dim";?>);
<?
  if (isset($riga[figli])) {
   $this->menu_javascript(1,$text.'_'.$start,$dim,$riga[figli]);
  }
  $start++;
 }
}
E ottengo quello che mi serve. EVVIVA ^_^
Ecco i risultati delle varie funzioni:
select() (chiamata da select_sezioni_array()) è una funzione che ritorna
un array del genere:
Array
(
    [0] => Array
        (
            [codice] => 59
            [sezione] => prova3
            [padre] => 58
            [ordine] => 100
        )
    [1] => Array
        (
            [codice] => 57
            [sezione] => prova
            [padre] => 47
            [ordine] => 100
        )
    [2] => Array
        (
            [codice] => 58
            [sezione] => prova2
            [padre] => 47
            [ordine] => 200
        )
    [5] => Array
        (
            [codice] => 47
            [sezione] => Pippo
            [padre] => 8
            [ordine] => 200
        )
    [35] => Array
        (
            [codice] => 8
            [sezione] => Palla
            [padre] => 0
            [ordine] => 800
        )
)
$risultato = $database->select_sezioni_array();
$risultato sarà
Array
(
    [8] => Array
        (
            [codice] => 8
            [sezione] => Palla
            [padre] => 0
            [ordine] => 800
            [figli] => Array
                (
                    [47] => Array
                        (
                            [codice] => 47
                            [sezione] => Pippo
                            [padre] => 8
                            [ordine] => 200
                            [figli] => Array
                                (
                                    [57] => Array
                                        (
                                            [codice] => 57
                                            [sezione] => prova
                                            [padre] => 47
                                            [ordine] => 100
                                        )
                                    [58] => Array
                                        (
                                            [codice] => 58
                                            [sezione] => prova2
                                            [padre] => 47
                                            [ordine] => 200
                                            [figli] => Array
                                                (
                                                    [59] => Array
                                                        (
                                                            [codice] =>
59
                                                            [sezione] =>
prova3
                                                            [padre] =>
58
                                                            [ordine] =>
100
                                                        )
                                                )
                                        )
                                )
                        )
                )
        )
)
Poi
$forms->menu_javascript(2,'Menu4','18,150',$risultato);
per avere
 Menu4_8=new Array("Palla","URL","", 1);
 Menu4_8_1=new Array("Pippo","URL","", 2,18,150);
 Menu4_8_1_1=new Array("prova","URL","", 0,18,150);
 Menu4_8_1_2=new Array("prova2","URL","", 1);
 Menu4_8_1_2_1=new Array("prova3","URL","", 0,18,150);
Scusatemi tutti se vi ho annoiato, ma magari vi capiterà
di dover scrivere un menu JS come questo :-))
Ciao,
