Lavender: Baum-Menü mit Perl erzeugen

Hallo zusammen,

nun zerbreche ich mir schon Tagelang den Kopf über folgendes Problem, aber irgendwo hat sich ein Denk-fehler eingeschlichen, der mich nicht weiterkommen lässt.

Ich habe eine Tabelle (MySQL) mit folgenden Daten:

id  childs  text          link
1    2     Brot             2
2    3     Korn             3
3    x     Mischkorn       http://
3    x     Roggen          http://
3    x     Weizen          http://
3    x     Hafer           http://
4    5     Weiß             5
5    x     WeißmitX        http://

Aussehen sollte der Baum so:

Brot
|
-- Korn
  |-- Mischkorn
  |-- Roffen
  |-- Weizen
  |-- Hafer
|
-- Weiß
  |-- WeißmitX

Aber egal wie ich es anstelle (ob mit childs oder mit parents) irgendwie geht es beim besten Willen nicht.

Kennt einer eine Lösungsmöglichkeit in Perl, die mich weiter bringt - wäre wirklich super.

Vielen Dank fürs Lesen.

Viele Grüße
Lavender

PS: die Angabe unter LINK öffnet im Fall einer Zahl den Baum mit dieser ID (sollte zumindest) - aber vielleicht ist mein ganzer Denkansatz falsch :(

  1. Hi,
    [...]

    PS: die Angabe unter LINK öffnet im Fall einer Zahl den Baum mit dieser ID (sollte zumindest) - aber vielleicht ist mein ganzer Denkansatz falsch :(

    Ja, das Datenmodell ist _etwas_ komisch. Wenn ich es richtig sehe, stehen komische Werte in den Spalten childs / link. Childs sieht aus, als seien das Anzahlen?! Falls das so ist: Die gehören natuerlich nicht in eine DB sondern können jederzeit mit einem Select Count ermittelt werden. Schreibt man derartige Aggregate in die DB musst Du die ja jedesmal bei Änderungen updaten. Ganz schlechte Idee...;)

    BTW: Was ist das für eine id-Spalte? Ein Primary Key jedenfalls nicht...

    Also, alles, was für dich wichtig ist, ist doch nur, ob (und wenn ja: welchen) parent-Satz ein Satz hat. Und das klappeerst Du rekursiv durch.

    Die Tabelle sollte also eher so aussehen, wobei id der Primaerschluessel ist.

    id  parentid text
    1    NULL Brot
    2    1 Korn
    4    2   Mischkorn
    5    2   Roggen
    6    2   Weizen
    7    2   Hafer
    8    1   Weiß
    9    8   WeißmitX

    Wenn der Kram innerhalb der gleichen Hierarchien jetzt einfach alphabetisch (oder nach dem PK) sortiert wird, ist alles gut. Wenn Du noch eine Sortierspalte brauchst, läufts Du wieder in die Falle, bei Einfügungen Updates über die folgenden Saetze machen zu muessen, was kein gutes Modell waere.

    cul,
    Falk

    1. Hallo Falk,

      vielen Dank für deine Antwort. Soweit sogut, nun habe ich jedem Wert einen eindeutigen Schlüssel (ID) und den Parent verpasst - die Frage ist allerdings, wie ich das von dir angesprochene, rekursive Sortieren / Durchlaufen umsetzen kann - Codetechnisch würde ich wieder mit vielen Variablen und If/Else arbeiten, wobei es bestimmt viel besser geht. Für einen weiteren Tipp wäre ich sehr dankbar.

      Viele Grüße
      Lavender

      1. Ich mache sowas mit einer Rekursion, Code siehe weiter unten,

        Hotte

        Die Liste enthält Gliederungspunkte einer Hierarchie und soll nun in HTML in einer <ul> </ul>
        mit den entsprechenden Einrückungen dargestellt werden.

          
        my @li = qw(  
         1  
         1.1  
         1.1.1  
         1.1.2  
         1.2  
         1.2.1  
         1.2.2  
         1.3  
         2  
         2.1  
         2.1.1  
         2.1.2  
         2.2  
         2.2.1  
         2.2.2  
         2.3  
        );  
          
        Es braucht eine Hilfsfunktion dir() welche für jeden Listenpunkt ein Array mit der nächsten  
        Ebene der Unterpunkte zurückgibt.  
          
        Dann kann mit einer Rekursion die Liste in HTML erstellt werden.  
          
        dir(\@li);      # gibt die Punkte der ersten Ebene zurück als Liste, hier 1 und 2  
        dir(\@li, '1'); # gibt die Unterknoten für 1 zurück als Liste  
          
        Zum Erstellen des Gesamtbaumes muss die traverse() Funktion über die Liste der Punkte  
        der ersten Ebene aufgerufen werden:  
          
        print "<ul>\n";  
        foreach my $d( dir(\@li) ){ traverse($d) }  
        print "</ul>\n";  
          
        Zum Darstellen eines Zweiges einfach die traverse() Funktion wie folgt aufrufen:  
          
        print "<ul>\n";  
        traverse('1');  
        print "</ul>\n";  
          
        ###########################################################################  
        # Die Rekursionsfunktion  
        sub traverse{  
         my $dir = shift;  
         my @subdirs = dir(\@li, $dir);  
         if(@subdirs){  
          print qq(<li> $dir <ul>\n);  
          foreach my $subdir(@subdirs){  
           traverse($subdir);  
          }  
          print "</ul></li>\n";  
         }  
         else{  
          print qq(<li> $dir </li>\n);  
         }  
        }  
        ###########################################################################  
        # Gibt die Unterordner der naechsten Ebene als liste zurueck  
        sub dir{  
         my ($ref, $dir) = @_;  
         my @a = @$ref;  
         my @al;  
         if($dir){  
          foreach my $n(@a){  
           if($n =~ /^$dir\.(\d+)$/){  
            $1 and push @al, "$dir.$1";  
           }  
          }  
         }  
         else{  
          foreach my $n(@a){  
           if($n =~ /^\d+$/){  
            push @al, $n;  
           }  
          }  
         }  
         return @al;  
        }  
        
        
        1. Danke euch allen.

          Viele Grüße
          Lavender

  2. Aber egal wie ich es anstelle (ob mit childs oder mit parents) irgendwie geht es beim besten Willen nicht.

    Wenn Du magst, kannst Du Dich mal mit Nested Sets beschäftigen. Zur Umsetzung in Perl könnte dieser Thread auf perlmonks.org interessant sein. Aber auch ohne nested sets könnte Dir Tree::Simple weiterhelfen, dessen Ansatz ist dem von Horst geposteten Code ähnlich.

    Siechfred

    --
    Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
    1. Hi ;)

      [..] Aber auch ohne nested sets könnte Dir Tree::Simple weiterhelfen, dessen Ansatz ist dem von Horst geposteten Code ähnlich.

      Jaja, Hotti fragt sich nun wieder nächtelang was zuerst da war:

      Das "Simple-Egg" oder das "Haselhuhn".

      Viele Grüße,
      Horst Haselhuhn

      1. Hallo Horst!

        Jaja, Hotti fragt sich nun wieder nächtelang was zuerst da war:
        Das "Simple-Egg" oder das "Haselhuhn".

        Das Atomic Egg, Du Gästebuch-Ano ;) - oder war der eine Eintrag mit der Mikrowelle doch nicht von Dir?

        Viele Grüße aus Frankfurt/Main,
        Patrick

        --

        _ - jenseits vom delirium - _
        [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
        Nichts ist unmöglich? Doch!
        Heute schon gegökt?
        1. Bonjour,

          Jaja, Hotti fragt sich nun wieder nächtelang was zuerst da war:
          Das "Simple-Egg" oder das "Haselhuhn".

          Das Atomic Egg, Du Gästebuch-Ano ;) - oder war der eine Eintrag mit der Mikrowelle doch nicht von Dir?

          Klar war der von mir, gut beobachtet Patti!!!

          Btw., ich hab neulich eine kleine Seite über AOC-Weine aus France geschrieben: http://rolfrost.de/franzwein.html

          A votre santé!

          Viele Grüße aus dem Schwarzwald,
          Hotte

          1. Hallo Horst!

            Klar war der von mir, gut beobachtet Patti!!!

            Nö, nicht gut beobachtet. Nur Dein Stil ist unverwechselbar (LOL)...

            http://rolfrost.de/franzwein.html

            Wäre an bestimmten Stellen berichtigungswürdig, ansonsten schon mal net schlecht... Werde mir das mal mit klarem Kopf durchlesen ;)

            A ta santé!

            Toujours!

            Im Übrigen ist »La Santé« ein Gefängnis mitten im Pariser 13er Bezirk. Mein Onkel wohnte dort. Ähm, nicht in La Santé, sondern fast gegenüber ;)

            Viele Grüße aus Frankfurt/Main,
            Patrick

            --

            _ - jenseits vom delirium - _
            [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
            Nichts ist unmöglich? Doch!
            Heute schon gegökt?