webForumDet fria alternativet

Träd list i PHP

11 svar · 1 028 visningar · startad av startail

startailMedlem sedan sep. 2000155 inlägg
#1

Ett litet problem som jag har om någon vet hur man skall göra det på lättast sätt eller har något förslag på kod från nått ställe...

Jag försöker få en träd meny som skall lagras i en db och skall kunna vara oändligt bred (eller ett max som man sätter senare)

Tex:

- Grupp 1
- - Undergrupp 1
- - - Undergrupp till ^
- - - - Undergrupp till ^
- - Undergrupp 2
- Grupp 2

Jag har suttit med det här problemet i några dagar nu och jag kommer inte fram till nått sätt att göra det på och lagra det i DB'n.

Är det nån som har ett tips på nånstans man kan se nån som gjort detta tidigare eller har nån kod snutt som gör det vore jag hemskt tacksam.

nkrantzMedlem sedan apr. 2002830 inlägg
#2

Det du vill göra är rekursiva funktionsanrop.

Skapa en tabell enl:
id | name | child_of

Sedan skriver du en funktion som listar alla rader som har child_of = 0 (som i ditt exempel Grupp 1). För varje gång du sedan får fram en ny rad så anropar du funktionen med den nya radens id nummer. På så sätt kommer du att skapa en hierki som du vill.

function menu($child_of)
	{
		$db = new Database;
		
		if (!isset($child_of))
		{
			$child_of = 0;
		}
		
		$SQL = "SELECT 
					id,
					name
				FROM 
					tabell
				WHERE 
					child_of = " . $child_of . "";
		
		$rSet = $db->dbQuery($SQL);
		
		while ($data = mysql_fetch_array($rSet))
		{
			echo $data[1];
			menu($data[0]);
		}
	}

Lycka till!

// Nippe

startailMedlem sedan sep. 2000155 inlägg
#3

Tack för svaret, men det blir en väldigt massa SQL anrop utav din lösning. Dock kanske jag kan använda ditt exempel med lite modifikation.

BäckmanMedlem sedan nov. 2001274 inlägg
#4

Går väl att bara köra ut alla poster man vill ha på en gång, och sedan använda den vektor som man får ut? Ska inte behöva bli mer än ett SQL-anrop.

startailMedlem sedan sep. 2000155 inlägg
#5

Har du något förslag på hur man kan göra det Bäckman ?

MatteMedlem sedan aug. 20002 975 inlägg
#6

Du skulle kuna testa något på det här hållet:

// Hämtar meny-elementen och lägger in en array
function make_menulist() {

   $sql = " SELECT id, name, child_of FROM tabell";
   $result = mysql_query($sql) or die(mysql_error());

   $menu_list = array();
   while ($row = mysql_fetch_assoc($result)) {

      $menu_list[$row['id']] = array(
         'name'   => $row['name'],
         'parent' => $row['child_of']
      );

   }

   return $menu_list;

}

// Bygger upp en flerdimensionell array av meny-arrayen
function get_tree($parent, $menu_list) {

   $menu = array();

   foreach ($menu_list as $key => $val) {

      if ($val['parent'] == $parent) {
         $menu[$key]['name'] = $val['name'];
         $menu[$key]['child'] = get_tree($key, $menu_list);
      }

   }

   return empty($menu) ? '' : $menu;

}

$menu_list = make_menulist();
$menu_tree = get_tree(0, $menu_list);

// För test, kolla hur din array ser ut
echo "<pre>";
print_r($menu_tree);
echo "</pre>";

Du får sedan loopa $menu_tree, troligtvis också det med en rekursiv funktion, och skriva ut din meny.

Där ['child'] är en array finns under-erlement, där ['child'] är en tom sträng finns inget under.

Du borde nog också lägga till en kolumn för länken i din tabell.

Koden är otestad, men den kan kanske ge dig lite idéer :)

startailMedlem sedan sep. 2000155 inlägg
#7

Tack, det ser väldigt bra ut och ser ut att funka som jag vill ha det. Jag skall testa det och se hur det blir.

nkrantzMedlem sedan apr. 2002830 inlägg
#8

startail skrev:

Tack för svaret, men det blir en väldigt massa SQL anrop utav din lösning. Dock kanske jag kan använda ditt exempel med lite modifikation.

Jag har en bra SQL-server ;) Nej, men du har helt rätt, det var mest för att illustrera hur du kan gå tillväga. Som de andra beskriver, ladda hem allt i en fråga och sortera sedan!

// Nippe

SkarreMedlem sedan apr. 20012 427 inlägg
#9

Nedanstående artikel hjälpte mig att komma igång med trädstrukturer. Den beskriver två olika tillvägagångssätt samt för- och nackdelar med dessa. Om det är ett ordentligt träd är nog "Modified Preorder Tree Traversal" att föredra.

http://www.sitepoint.com/article/1105

MickeA.comMedlem sedan feb. 20034 441 inlägg
#10

Har fast med det här nu... Använder Maltes kod ovan och får ut:

Array
(
    [1] => Array
        (
            [name] => Start page
            [child] => 
        )

    [23] => Array
        (
            [name] => Händelser
            [child] => Array
                (
                    [24] => Array
                        (
                            [name] => Publika nyheter
                            [child] => Array
                                (
                                    [27] => Array
                                        (
                                            [name] => Lägg till
                                            [child] => 
                                        )

                                    [28] => Array
                                        (
                                            [name] => Översikt
                                            [child] => 
                                        )

                                )

                        )
...

Men sen då? Har försökt loopa ut min array, men förstår inte alls hur jag ska göra. Har testat med foreach-loopar hit och dit. När man söker på detta ämne finns nästan bara artiklar/information om hur man gör motsatsen, t.ex. skapar en array likt den ovan av en katalogstruktur.

Men hur får jag ut array'en ovan som en unsorted list?

Tack!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#11

Har nu kommit såhär långt:

function test($arr, $level){
	$foo = "<ul>\n";
	foreach($arr as $key => $value){
		
		$foo .= "<li><a href=\"#\">" . $arr[$key]['name'] . "</a>\n";
		if(is_array($arr[$key]['child'])){
			$foo .= test($arr[$key]['child'], $level + 1);
		}
		$foo .= "</li>\n";
	}
	$foo .= "</ul>\n";
	return $foo;
}

Vilket skriver ut hela trädet som en nästlad lista. Men om jag nu vill ha ut samma formatering fast i en selectlista? Precis som listan "Forum Jump" här på wF, nere till höger på varje undersida. Får verkligen inte till det...

Tacksam för förslag.

/r Jag vill alltså få ut resultatet såhär:

Main
   Sub
   Sub
      Node
   Sub
Main
Main
   Sub
      Node
      Node
...
MickeA.comMedlem sedan feb. 20034 441 inlägg
#12

Löste det med:

function parent_list($arr, $level = 0) {
	$list = "";
	$level++;
	foreach($arr as $key => $value){
		$list .= "<option value=\"" . $arr[$key]['id'] . "\" style=\"padding-left: " . ($level > 1 ? $level * 10 . "px" : "5px") . ";\">- " . $arr[$key]['name'] . "</option>\n";
		if(is_array($arr[$key]['child'])){
			$list .= parent_list($arr[$key]['child'], $level);
		}
	}
	return $list;
}
252 ms totalt · 3 externa anrop · v20260731065814-full.0e50b1ef
125 ms — hämta forumlista (db)
125 ms — hämta statistik (db)
125 ms — hämta tråd, inlägg och bilagor (db)