Christian S.: (PHP) Navigation

Hi,

kann mir jemand sagen wie man am besten eine Navigationskonzept mit PHP erstellt?

Ich habe mir folgendes gedacht:

In einer XML-Datei speichere ich die baumartige Struktur, etwa so:

  
<Menu>  
   <Item href="/privat" title="Privat">  
      <Item href="/fotos" title="Fotos" />  
      <Item href="/hobby" title="hobby" />  
   </Item>  
   <Item href="/artikel" title="Artikel">  
      <Item href="/php" title="PHP" />  
   </Item>  
</Menu>  

Ginge so eine Stuktur überhaupt? Da <Item> einmal ein Endtag hat, und einmal nicht. Wie besser?

Daraus würde ich dann eine entsprechende HTML Strutkur, vermutlich mit <ul>/<li> bauen, jenachdem wie ich es brauche.

Weiterhin würde ich dann auf jeder PHP Seite eine Variable setzen, die sich eindeutig in o.g. Baum wiederfinden lässt. Evtl. sollte ich dann mit IDs arbeiten. $_SERVER['PHP_SELF'] o.ä möchte ich nicht als "ID" verwenden, da die Navigation dann von der physikalischen Struktur abhängig wäre.

Habe ich das <Item> gefunden, würde ich den Tree aufsteigen, um eine Breadcrumb-Navigation zu machen.

z.B.:
Wenn man sich auf der PHP Seite befindet, sähe es so aus:

Home -> Artikel -> PHP

Wobei PHP nicht verlinkt ist (da aktuelle Seite), der Rest schon. Hat ja jeder schon mal gesehen.

Diese Seite kann dann aber z.B. mehrere Artikel enthalten, die nicht(!) mehr in der XML Datei stehen, sondern aus einer anderen Quelle (DB) kommen können.

Wie würde ich es dann z.B. hinbekommen, dass die Navigation etwa so aussieht, wenn man auf einen Artikel klickt:

Home -> Artikel -> PHP -> Artikel 1

Man möchte ja von Artikel 1 wieder zurück auf die Artikelübersicht ("PHP").

Bräuchte man für so etwas einen Art Navigationsmanager oder BreadcrumbManager?

Also ich würde gerne wissen, wie so das Grundkonzept einer guten Navigation aussieht.
Oder sollte man die Navigation lieber in eine Datenbank schreiben?

Wie ist es denn in SELFHTML gemacht worden? Dort ist es doch genauso. (nur ohne PHP).

Gruß!

  1. Hi,

    kann mir jemand sagen wie man am besten eine Navigationskonzept mit PHP erstellt?

    Meine Navigation mit Breadcrumbs und so, basiert auf einer INI-Datei, ich hab das mit Perl realisiert und aufgeschrieben:

    http://rolfrost.de/webtree.html

    Jow, was mit Perl geht, ist möglicherweise auch mit PHP zu machen.

    Viele Grüße,
    Horst Haselhuhn

  2. Hallo Christian,

    In einer XML-Datei speichere ich die baumartige Struktur ...
    Ginge so eine Stuktur überhaupt? Da <Item> einmal ein Endtag hat, und einmal nicht.

    Ja.

    Wie besser?

    Strukturell mag <items> besser sein, generell ist es aber seitens XML kein Problem sowohl #PCDATA als auch Elemente (in sich selbst) zu verschachteln.

    Daraus würde ich dann eine entsprechende HTML Strutkur, vermutlich mit <ul>/<li> bauen, jenachdem wie ich es brauche.

    Mir stellt sich an diesem Punkt aber eine andere Frage aus der Überlegung heraus, dass Du eine Datenstruktur hast, die ursprünglich die Lage von zu servierenden Resourcen in einem Dateisystem abbildet. Die Abbildung (Abstraktion) lässt sich in der gewählten Programmiersprache mit rekursiv erstellten, mehrdimensionalen Datenfeldern (Array) für PHP am sinnvollsten verarbeiten. Soweit so gut. Warum willst Du mittels XML eine weitere Abstraktion erstellen? Was spricht gegen ein Speichern der Datenstruktur seitens PHPs durch serialize() (und im umgekehrten Fall unserialize()? Kann auf eine Zwischenspeicherung ganz verzichtet werden, weil der Aufwand, den Du in jedem Fall betreiben willst, des permanent Auslesens der Verzeichnisstruktur gleich kommt?

    Weiterhin würde ich dann auf jeder PHP Seite eine Variable setzen, die sich eindeutig in o.g. Baum wiederfinden lässt. Evtl. sollte ich dann mit IDs arbeiten. $_SERVER['PHP_SELF'] o.ä möchte ich nicht als "ID" verwenden, da die Navigation dann von der physikalischen Struktur abhängig wäre.

    Wenn Du davon ausgehst, dass die Web-Struktur der Verzeichnisstruktur entspricht, zeigen sich bei einem permanenten Auslesen bereits hier erste Vorteile. Wenn Du Dir nicht selbst einen XML-Parser schreibst, muss Dein Programm bei jeder Anfrage die gesamte XML-Struktur einlesen und verarbeiten, denn so sind die Verfügbaren XML-Parser PHPs nun mal geschrieben. Andernfalls können bei einem Direkten Auslesen der Struktur immer die navigationsbedingten Teile ausgelesen werden.

    Habe ich das <Item> gefunden, würde ich den Tree aufsteigen, um eine Breadcrumb-Navigation zu machen.

    Unter selber Annahme, der der Kongruenz von Web- und Verzeichnisstruktur, müsstest Du jeweils nur von getcwd() $_SERVER['DOCUMENT_ROOT'] subtrahieren und könntest mittels [link:http://de3.php.net/manual/de/function.explode.php@title=explode]('/' /* bei Win: '\' */,$diff); die aufsteigende Navigation abstrahieren.

    ...
    Bräuchte man für so etwas einen Art Navigationsmanager oder BreadcrumbManager?

    Keinesfalls.

    Also ich würde gerne wissen, wie so das Grundkonzept einer guten Navigation aussieht.
    Oder sollte man die Navigation lieber in eine Datenbank schreiben?

    Schieße nicht auf Deinen Spatz! Wenn Du zu solchen Kanonen greifst, wird es Dir einstweilig die Hand abreißen.

    Gruß aus Berlin!
    eddi

    --
    Der Verweis auf die Grundlagen Deines Handelns, ist das Joch zur Freiheit.
    Aber so gilt: Allen Leuten Recht getan, ist keine Kunst, weil's jeder kann.
    1. Hi,

      danke für deine Antwort, auch wenn sie sich etwas schwerfällig lesen lässt.

      Mir stellt sich an diesem Punkt aber eine andere Frage aus der Überlegung heraus, dass Du eine Datenstruktur hast, die ursprünglich die Lage von zu servierenden Resourcen in einem Dateisystem abbildet. Die Abbildung (Abstraktion) lässt sich in der gewählten Programmiersprache mit rekursiv erstellten, mehrdimensionalen Datenfeldern (Array) für PHP am sinnvollsten verarbeiten. Soweit so gut. Warum willst Du mittels XML eine weitere Abstraktion erstellen? Was spricht gegen ein Speichern der Datenstruktur seitens PHPs durch serialize() (und im umgekehrten Fall unserialize()? Kann auf eine Zwischenspeicherung ganz verzichtet werden, weil der Aufwand, den Du in jedem Fall betreiben willst, des permanent Auslesens der Verzeichnisstruktur gleich kommt?

      So ganz versteh ich es nicht.

      Ich wollte die Navigation in XML abbilden, statt in einem PHP Array, weil ich denke dass es sauberer und einfacherer wartbar ist.
      Das ist etwa so wie die Frage: "CSS inline schreiben oder extern einbinden".

      Wenn ich das richtig verstehe, sollte ich die Struktur in PHP erzeugen, und dann serialisiert ablegen? Und wenn ich sie dann wieder brauche, wieder deserialisieren?

      Ich glaube ich hab es nicht verstanden, was du willst, denn es doch egal, ob die Daten dann in XML vorliegen oder binär.

      Wenn Du davon ausgehst, dass die Web-Struktur der Verzeichnisstruktur entspricht, zeigen sich bei einem permanenten Auslesen bereits hier erste Vorteile. Wenn Du Dir nicht selbst einen XML-Parser schreibst, muss Dein Programm bei jeder Anfrage die gesamte XML-Struktur einlesen und verarbeiten, denn so sind die Verfügbaren XML-Parser PHPs nun mal geschrieben. Andernfalls können bei einem Direkten Auslesen der Struktur immer die navigationsbedingten Teile ausgelesen werden.

      Davon möchte ich ja nicht ausgehen. Physikalisch kann z.B. eine andere Struktur vorliegen, als die die man später auf der Webseite sieht.

      Selbst wenn, müsste ich immer noch bei jeder Anfrage das XML abparsen, um aus dem physikalischen Pfad einen formatierten Titel (der dann irgendwo in der XML datei steckt) herauszufinden.

      Unter selber Annahme, der der Kongruenz von Web- und Verzeichnisstruktur, müsstest Du jeweils nur von getcwd() $_SERVER['DOCUMENT_ROOT'] subtrahieren und könntest mittels [link:http://de3.php.net/manual/de/function.explode.php@title=explode]('/' /* bei Win: '\' */,$diff); die aufsteigende Navigation abstrahieren.

      ja, dann müssten meine Verzeichnisse genauso heißen, wie sie auch in der Navigation zu sehen sein sollen. D.h ich könnte keine Umlaute oder Leerzeichen benutzen.

      Bräuchte man für so etwas einen Art Navigationsmanager oder BreadcrumbManager?

      Keinesfalls.

      Und wie würde man so was dann lösen (mein Beispiel mit den dynamischen Artikeln, die aus ner DB kommen)?

      Schieße nicht auf Deinen Spatz! Wenn Du zu solchen Kanonen greifst, wird es Dir einstweilig die Hand abreißen.

      vermutlich...

      Also ich mach es jetzt im moment so, dass ein XML File hab, (ähnlich wie beschrieben).
      Dort steht die baumartige Struktur drin, und zu jedem <item> habe ich ein Attribut "href" und "title".
      Bei einer Anfrage, wird $_SERVER['PHP_SELF'] mit jedem href verglichen, bis eine Übereinstimmung gefunden wurde. Während der rekursion merk ich mir den Pfad und kann so mit die Navigation erstellen. Und das "title" Attribut dient gleichzeitig als <title> und <h1> Wert meiner Seite...

      Gruß!

      1. Re:

        So ganz versteh ich es nicht.

        Ich wollte die Navigation in XML abbilden, statt in einem PHP Array, weil ich denke dass es sauberer und einfacherer wartbar ist. Das ist etwa so wie die Frage: "CSS inline schreiben oder extern einbinden".

        Du bist beim Abbilden der Verzeichnisstruktur durch XML aber nicht in(nerhalb) einer Programmiersprache, die Instanzen aus Objekten formt. Das heißt, dass Du bei Veränderungen der Verzeichnisstruktur _zusätzlich_ Deine XML-Daten(bank) zu verändern hast. Manuell oder maschinell ist egal. Du betreibst Mehraufwand.
         Daher hinkt der Vergleich zu CSS enorm. Sagen wir ein HTML-Dokument (mittels DOM betrachtet ist dem ja so), sei Deine Verzeichnisstruktur. CSS arbeitet aber ("CLASS") Objekten.

        /* Objekte       Eigenschaften */  
          
        body            {margin:0;color:grey}  
        ul              {padding:10px;font-size:1.2em}  
        li.sp1          {padding:0;margin:0}
        

        Veränderst Du nun das Dokument benötigt aber das style sheet keiner Anpassung. Weil das CSS-realisierende Programm auf die html- O bjekte (dOm) zurückgreift.

        Wenn ich das richtig verstehe, sollte ich die Struktur in PHP erzeugen, und dann serialisiert ablegen? Und wenn ich sie dann wieder brauche, wieder deserialisieren? Ich glaube ich hab es nicht verstanden, was du willst, denn es doch egal, ob die Daten dann in XML vorliegen oder binär.

        Wenn sich tatsächlich erweisen sollte, dass es Sinn macht, die Struktur niederzuschreiben und dafür umzuformulieren, ist das nur eine Alternative, die PHP erheblich weniger Systemresourcen verbrauchen lässt. Darin liegt ein weiter Vorteil gegenüber XML.

        Wenn Du davon ausgehst, dass die Web-Struktur der Verzeichnisstruktur entspricht, zeigen sich bei einem permanenten Auslesen bereits hier erste Vorteile. Wenn Du Dir nicht selbst einen XML-Parser schreibst, muss Dein Programm bei jeder Anfrage die gesamte XML-Struktur einlesen und verarbeiten, denn so sind die Verfügbaren XML-Parser PHPs nun mal geschrieben. Andernfalls können bei einem Direkten Auslesen der Struktur immer die navigationsbedingten Teile ausgelesen werden.

        Davon möchte ich ja nicht ausgehen. Physikalisch kann z.B. eine andere Struktur vorliegen, als die die man später auf der Webseite sieht.

        Ein System aus alias wird Dir dauerhaft Mehrarbeit und Potential an Fehlern bieten. Maschinelles Abarbeiten der Web-Strukturanpassungen ist nicht mehr möglich. Willst Du Dich dauerhaft, arbeitstechnisch gesehen, unentbehrlich machen?

        Selbst wenn, müsste ich immer noch bei jeder Anfrage das XML abparsen, um aus dem physikalischen Pfad einen formatierten Titel (der dann irgendwo in der XML datei steckt) herauszufinden.

        Unter selber Annahme, der der Kongruenz von Web- und Verzeichnisstruktur, müsstest Du jeweils nur von getcwd() $_SERVER['DOCUMENT_ROOT'] subtrahieren und könntest mittels [link:http://de3.php.net/manual/de/function.explode.php@title=explode]('/' /* bei Win: '\' */,$diff); die aufsteigende Navigation abstrahieren.

        ja, dann müssten meine Verzeichnisse genauso heißen, wie sie auch in der Navigation zu sehen sein sollen. D.h ich könnte keine Umlaute oder Leerzeichen benutzen.

        $replace=array(  
                'Ae'=>'Ä',  
                'ae'=>'ä',  
                '+' =>' '  
                # und so weiter  
        );  
        [link:http://de3.php.net/manual/de/language.functions.php@title=function] fs2navi($name,$richtung=true){  
                [link:http://de3.php.net/manual/de/language.control-structures.php#control-structures.if@title=if](!$richtung){  
                       $replace=[link:http://de3.php.net/manual/de/function.array-flip.php@title=array_flip]($GLOBALS['replace']);  
                }  
                [link:http://de3.php.net/manual/de/control-structures.foreach@title=foreach]($replace as $k=>$v){  
                        $name=[link:http://de3.php.net/manual/de/function.str-replace.php@title=str_replace]($k,$v,$name);  
                }  
                [link:http://de3.php.net/manual/de/function.return.php@title=return]($name);
        

        Somit hast Du keine Probleme _direkt_ auf die Struktur zuzugreifen und deren ursprünglichen Informationsgehalt, nämlich der der in den Verzeichnis- und Dateinamen, voll nutzen ohne weitere Maschinerie (XML und seine parse gang) zu benötigen.

        Also ich mach es jetzt im moment so, dass ein XML File hab, (ähnlich wie beschrieben).
        Dort steht die baumartige Struktur drin, und zu jedem <item> habe ich ein Attribut "href" und "title".
        Bei einer Anfrage, wird $_SERVER['PHP_SELF'] mit jedem href verglichen, bis eine Übereinstimmung gefunden wurde. Während der rekursion merk ich mir den Pfad und kann so mit die Navigation erstellen. Und das "title" Attribut dient gleichzeitig als <title> und <h1> Wert meiner Seite...

        Oh mein Gott. Du wirft Deinen Spatz ja vor die Säue? -,-

        Gruß aus Berlin!
        eddi

        --
        Der Verweis auf die Grundlagen Deines Handelns, ist das Joch zur Freiheit.
        Aber so gilt: Allen Leuten Recht getan, ist keine Kunst, weil's jeder kann.
        1. hi,

          Somit hast Du keine Probleme _direkt_ auf die Struktur zuzugreifen und deren ursprünglichen Informationsgehalt, nämlich der der in den Verzeichnis- und Dateinamen, voll nutzen ohne weitere Maschinerie (XML und seine parse gang) zu benötigen.

          Naja, der Informationsgehalt eines Dateinamens oder Ordnernamens geht ja fast gegen null.
          Wie du schon gesagt hast, bräuchte man schon mal diese replace Funktion.

          Dann kommt mal als nächstes auf die Idee, und möchte zu jedem "Ordner" alias "Menupunkt" auch eine Beschreibung als Tooltip anzeigen.

          Allein der Ordnernamen gibt doch nicht viel her.

          Oder man möchte plötzlich mehrsprachigkeit haben. Früher oder später braucht man einfach eine neue Struktur, da allein der Ordnername nicht mehr ausreicht.

          Außerdem woher weiß man überhaupt, in welche Ordner man reinnavigieren kann?

          Angenommen ich habe folgende Struktur:

          /Fotos
            /Urlaub1
            /Urlaub2
            /js
            /css

          Würde ich die Navigation doch automatisch aus der physikalischen Struktur erstellen, würden /js und /css mit in der Navigation auftauchen, obwohl diese Ordner ja keine Seite darstellen sollen.
          Dann bräuchte man wieder eine Art Filter oder so.

          Gruß!

          1. Re:

            Somit hast Du keine Probleme _direkt_ auf die Struktur zuzugreifen und deren ursprünglichen Informationsgehalt, nämlich der der in den Verzeichnis- und Dateinamen, voll nutzen ohne weitere Maschinerie (XML und seine parse gang) zu benötigen.

            Naja, der Informationsgehalt eines Dateinamens oder Ordnernamens geht ja fast gegen null.
            Wie du schon gesagt hast, bräuchte man schon mal diese replace Funktion.

            Mit den genannten Stichworten kann ich Dir da nur recht geben. Von diesen Standpunkt ausgehend, geht er gegen Null.

            Dann kommt mal als nächstes auf die Idee, und möchte zu jedem "Ordner" alias "Menupunkt" auch eine Beschreibung als Tooltip anzeigen.

            Allein der Ordnernamen gibt doch nicht viel her.
            Oder man möchte plötzlich mehrsprachigkeit haben. Früher oder später braucht man einfach eine neue Struktur, da allein der Ordnername nicht mehr ausreicht.

            Dateisysteme mit Metadaten sind da natürlich schon was geiles. Du wirst mich komplett verstehen, was ich meine, was Du dort doppelt machst, wenn Du Dir WinFS - Technik ansiehst. Alternative Metadaten speichernde Dateisysteme gibt es selbstverfreilich auch: ZFS

            Außerdem woher weiß man überhaupt, in welche Ordner man reinnavigieren kann?

            Angenommen ich habe folgende Struktur:

            /Fotos
              /Urlaub1
              /Urlaub2

            /.js
                 /.css

            Wie bei *nix üblich ^.([A-z0-9]+)$ ist nicht fürs Publikum.

            Gruß aus Berlin!
            eddi

            --
            Der Verweis auf die Grundlagen Deines Handelns, ist das Joch zur Freiheit.
            Aber so gilt: Allen Leuten Recht getan, ist keine Kunst, weil's jeder kann.
            1. Also schön. Lassen wir mal die Vorstellung von Metadaten der Dateisysteme, die im Hinblick auf die herrschende Situation der shared hostings eine unrealistische Wolkenträumerei auch für die absehbare Zukunft bleiben wird. (BTW: Läuft bei strato eigentlich immer noch PHP 4.0.6?)

              Demnach ist Deine weite Betrachtung der Problematik, die auf den ungenügenden Informationsgehalt der Abstraktion des Dateisystems abzielt, schon ein triftiger Grund XML einzusetzen. Wie gefällt Dir folgende DTD?

              <!ELEMENT menu      (language)+>  
              <!ELEMENT language  (dir, file)*>  
              <!ELEMENT dir       (file)*>  
              <!ELEMENT file      EMPTY>  
                
              <!ATTLIST menu  
                 date            CDATA    #IMPLIED  
                 defaultcharset  CDATA    #REQUIRED  
                 defaulttype     CDATA    #REQUIRED  
              
              >  
              
              <!ATTLIST language  
                 charset         CDATA    #IMPLIED  
                 id              NMTOKEN  #REQUIRED  
              
              >  
              
              <!ATTLIST dir  
                 description     CDATA    #IMPLIED  
                 id              NMTOKEN  #IMPLIED  
                 uri             CDATA    #REQUIRED  
              
              >  
              
              <!ATTLIST file  
                 description     CDATA    #IMPLIED  
                 id              NMTOKEN  #IMPLIED  
                 type            CDATA    #IMPLIED  
                 uri             CDATA    #REQUIRED  
              
              >
              
              

              Damit würdest Du die Problematik noch weiter angehen und kannst vom Webserver unabhängig (nach dieser DTD aber abhängig von der Sprache) Dinge programmweit regeln, die Zeichensatz und MIME-Type einschließen. Im Sinne einer Ausnutzung von PATH_INFO via PHP fällt dabei sogar recht portables Gesamtkonzept zur Strukturierung eines Webs ab. ;)

              Gruß aus Berlin!
              eddi

              --
              Der Verweis auf die Grundlagen Deines Handelns, ist das Joch zur Freiheit.
              Aber so gilt: Allen Leuten Recht getan, ist keine Kunst, weil's jeder kann.
              1. Hi,

                Demnach ist Deine weite Betrachtung der Problematik, die auf den ungenügenden Informationsgehalt der Abstraktion des Dateisystems abzielt, schon ein triftiger Grund XML einzusetzen. Wie gefällt Dir folgende DTD?

                So ähnlich habe ich es ja. nur ohne das language Element.

                Problem ist halt bei der Sprache, dass man dann für jede Sprache so eine XML Datei braucht. Also wenn man mal die Struktur ändern will, muss man es in allen ändern.

                Aber genug dieser Diskussion, denn die Sprache war nur so eine überlegung von mir und ist derzeit nicht wichtig.

                Ich versteh nur nicht ganz, wozu der Mimetype und das Datum gebraucht wird.

                Gruß
                Christian

                1. Re:

                  <?xml version="1.1" encoding="iso-8859-1"?>  
                  <!DOCTYPE menu SYSTEM  
                     "-//Christian S.//DTD webstruct V 1.0//DE"  
                     "[pref:t=172572;m=1131320]"  
                  
                  >  
                  
                  <menu defaultcharset="iso-8859-1" defaulttype="text/html">  
                     <language id="de">  
                        <dir uri="projekte">  
                           <dir uri="php" description="Alle, was ich in PHP kann">  
                              <file uri="index" description="Überblick"/>  
                              <file uri="beispiele"  
                            description="Ausführbare Programme"  
                                   type="application/xhtml+xml"/>  
                              <file uri="offen"  
                            description="Quellcode"  
                                   type="application/x-httpd-php-source"/>  
                           </dir>  
                        </div>  
                     </language>  
                     <language id="fr" charset="utf-8" />  
                  </menu>
                  

                  In dem Sinne sind "(default)type" und "(default)charset" auch nur Überlegungen. Hier in diesem Beispiel kannst Du verzeichnisweite Einstellungen vornehmen (ähnlich einer .htaccess, die eben nicht jeder Webserver hat[!]), die mit einer Programmlogik dann zu HTTP-Headern geformt werden könnten. Hinsichtlich der Empfehlung seitens des w3c auf Datei.(endungen) zu verzichten, macht das auch Sinn. PATH_INFO wird nicht nur von PHP unterstützt - weitest mögliche Portabilität, die weder an Programmiersprache, noch an Webserver gebunden ist.

                  Das Attribut "date" kann zur maschinellen Verarbeitung, als Rückbestätigung für ein Programm Veränderungen vorzunehmen ganz nützlich, herangezogen werden, wenn Du eine Programmlogik dafür entwickeln willst, zwangsläufige Änderungen zu automatisieren.

                  Gruß aus Berlin!
                  eddi

                  --
                  Der Verweis auf die Grundlagen Deines Handelns, ist das Joch zur Freiheit.
                  Aber so gilt: Allen Leuten Recht getan, ist keine Kunst, weil's jeder kann.