phpbar.de logo

Mailinglisten-Archive

[php] Baumstruktur ?

[php] Baumstruktur ?

=?iso-8859-1?Q?Bj=F6rn_Schotte?= bjoern_(at)_baer.mayn.de
Wed, 6 Oct 1999 23:59:41 +0000


> Haste so ein  Ding denn irgentwo ?

*ÄCHZ* hier mal als quick shot, ausführlicher
Artikel folgt.

Kleiner Screenshot (10 KB GIF) zu finden
auf: <http://www.php-center.de/winex.gif>

Here we go ...

<?

# WindowsExplorer artige Navigationsstruktur mit beliebig
# vielen Tiefen anhand einer Datenbank.
#
# (C) by Björn Schotte, 1999

/*
   Datenstruktur, graphisch:

                         -------------------
                         |Wurzel, imaginäre|
                         |ID 0             |
                .------  -------------------  ------------.
               /             |            |                \
1. Ebene      Kultur  --  Rathaus   --    Jugend    --     Bildung
   ID           1            2               3                4
   Vater        0            0               0                0

2.Ebene       /   \                                        /    \
             /   Kino                                     /      \
            / (ID=5, Vater=1)                          Schule     \
           Theater                            (ID=10,Vater=4)      \_VHS                                            
      (ID=6, Vater=1)                                             (ID=11, Vater=4)
         /
        /
      Aufführungen           <---.
     (ID=8, Vater=6)              \ 3. Ebene
         

Idee: jeder "Bereich" in der Baumstruktur hat einen Pointer auf den
      Vater.

Zweite Idee: um sich spätere Zugriffe zu sparen, wird der Weg vom
      aktuellen Bereich bis zur Wurzel in der Datenbankstruktur
      selbst auch noch verzeichnet (dies sei der "Pfad" genannt).
      Beispiel:

      Pfad des Bereichs "Theater" (ID=6): 1:6
      Pfad des Bereichs "Aufführungen" (ID=8): 1:6:8

      Wichtig ist, daß am Ende des Pfads immer nochmals die eigene
      ID steht, sonst kann die Funktion nicht "reinspringen".

      Der Pfad wird durch eine Funktion createbaumarray() aufgebaut,
      die, von der ID des Bereichs ausgehend, bis zur Wurzel hoch ein
      Array mit den IDs der Bereiche aufbaut (also $a[0]=8, $a[1]=6,
      $a[2]=1 für den Bereich "Aufführungen") und dieses Array mittels
      der Funktion reverse() (zu finden auf phpwizard.net) umkehrt.
      Danach wird mittels implode("beliebigertrenner",$a); das Array
      in einen String umgewandelt und in die Datenbank abgespeichert.


Der Sourcecode des linken Frames, in dem die Baumstruktur dargestellt
wird, schaut in etwa so aus: 

<a href="<? echo $PHP_SELF; ?>">Home</a><br><br>
<?
  $result=mysql_query("SELECT * from katalog WHERE k_id='$kid'");
  $row=mysql_fetch_array($result);
  $pfad=$row[k_liste];
  $mybaum=split(":",$pfad);
  // Baumstruktur der Datenbank aufbauen.
  echo "<A HREF=\"links.php3\" target=\"links\"><IMG SRC=\"e_home.gif\" ALT=\"*\" align=top border=0></A>[<A HREF=\"neu.php3?kvater=0\" target=\"rechts\">N</A>]<BR>\n";
  $zaehler=0;
  showbaum(0);

?>

Ihm übergeben wird via GET-Parameter die Variable $kid, die besagt,
in welchen Bereich er springen soll. Dann wird die rekursive Funktion
mit dem Parameter 0 aufgerufen, die dann den Baum aufbaut.

Abriss aus der Datenstruktur:

CREATE TABLE katalog(
  k_id NOT NULL DEFAULT '0' auto_increment,        # eigene ID
  k_vater INT,                                     # ID des Vaters
  k_liste CHAR(255),                               # Listenpfad
  k_name CHAR(255),                                # z.B. der Name des Pfades
  PRIMARY KEY(k_id)
);

Selbstverständlich muß bei jeder Änderung eines Bereichs (d.h. wenn
ein Bereich z.B. plötzlich einen anderen Vater bekommt) das Feld
k_liste aktualisiert werden, mittels der Funktion createbaumarray():

function reverse( &$inarray ) {
  for( $i = 0; $i < sizeof( $inarray ); $i++ )
    $outarray[ $i ] = $inarray[ sizeof( $inarray ) - $i - 1 ];
  $inarray = $outarray;
}


## Erstellt ein Array mit dem Pfad bis zur Wurzel, ausgehend vom
## Bereich $bereichsid.
function createbaumarray($bereichsid) {
  $a[]=$bereichsid;
  while ($bereichsid != 0) {
    $result=mysql_query("SELECT * FROM katalog WHERE k_id='$bereichsid'");
    $row=mysql_fetch_array($result);
    $oid=$row[k_vater];
    if ($oid != 0) {
     $a[]=$oid;
    }
    $bereichsid=$oid;
  }
  reverse($a);
  return $a;
}

*/


$gastro_mysqlhost="localhost";
$gastro_mysqluser="www";
$gastro_db="gastro";

mysql_connect($gastro_mysqlhost,$gastro_mysqluser,"");
mysql_select_db($gastro_db);

# Funktion für showbaum
#
# Macht $anz Linien nebeneinander.
#
function makelinie($anz) {
  for ($i=0; $i<=$anz; $i++) { echo "<IMG ALIGN=top SRC=\"e_linie.gif\" WIDTH=20 HEIGHT=16 ALT=\"\">"; }
}

# Zeigt die Baumstruktur mit Bereichen/Seiten rekursiv an.
# Hierbei ist eine beliebige Tiefe für die Bereiche möglich.
#
function showbaum($mybid) {
  GLOBAL $zaehler,$mybaum;
  $query="SELECT * FROM katalog WHERE k_vater='$mybid' ORDER BY k_name";
  if ($result=mysql_query($query)) {
    while ($row=mysql_fetch_array($result)) {
      $name=$row[k_name]; $kid=$row[k_id]; $koid=$row[k_vater];
      $name=eregi_replace(" ","&nbsp;",$name);
      if ($zaehler>0) {
        makelinie($zaehler-1);
      }
      echo "<IMG ALIGN=top SRC=\"e_t-stueck.gif\" WIDTH=20 HEIGHT=16 ALT=\"\">";

      # links.php3 ist oben erwähnter linker Frame.
      #
      # Er wird mit der ID des Bereiches aufgerufen, d.h. der Funktion
      # wird gesagt: "Springe doch bitte bei dem Bereich mit der ID $kid
      # eine Ebene tiefer"
      echo "<A HREF=\"links.php3?kid=$kid\"><IMG ALIGN=top SRC=\"e_verzeichnis.gif\" WIDTH=20 HEIGHT=16 border=0 ALT=\"\">$name</A>&nbsp;";
      echo "<BR>\n";
      
      # Seiten zum Bereich anzeigen
      #
      if (($zaehler<count($mybaum)) && $mybaum[$zaehler]==$kid) {
        # Alles selektieren, was dazu gehört.
        $myres=mysql_query("select * from meineseiten where meineseiten.katalog=$kid ...");
        while ($myrow=mysql_fetch_array($myres)) {
          $name=$myrow[g_name];
          $name=str_replace(" ","&nbsp;",$name);
          if ($zaehler>0) {
            makelinie($zaehler);
          }
          # Hier kann dann ein Anchor mit dem Editieren der jeweiligen Seite/File/hau-mich-tot
          # stehen
          echo "<a href=\"meine_edit_funktion.php3?meineid=$myrow[g_id]\" target=\"rechts\"><b>bla</b></a><br>\n";
        }
      }
      #
      # Anzeigeende

      # Wenn die Laufvariable $zaehler kleiner ist als das Array meiner
      # Pfadliste und gleichzeitig die ID im Array an der aktuellen
      # Position $zaehler gleich mit der ID meines Bereichs, den ich anhand
      # des SELECTs weiter oben ausgegeben habe, dann erhöhe den Zähler um
      # eins, rufe die Funktion erneut auf (d.h. stelle alles dar, was unterhalb
      # des Bereiches, den ich angeklickt habe, existiert), und springe mit
      # dem Zähler wieder eins zurück.
      if (($zaehler<count($mybaum)) && $mybaum[$zaehler]==$kid) { $zaehler++; showbaum($kid); $zaehler--; }
    }
  }
}

?>


php::bar PHP Wiki   -   Listenarchive