Malcolm Beck´s: Inhalt der Aufrufenden Seite finden, Nested Sets

مرحبا

ich arbeite gerade an einem kleinen CMS für mich (so wie immer ;)) und ich habe es endlich geschafft, das ganze sauber umzusetzen.
Also das die Navigation unendlich verschachtelt werden kann, und die erzeugten URI wie Pfadangaben aussehen.

Bsp.

/de/seite_1
/de/seite_1/seite_1_2
/de/seite_1/seite_1_2/seite_1_2_3

Soweit funktioniert das ganze jetzt auch Wunderbar, nur, wie suche ich jetzt nach dem passenden Inhalt für Seite „seite_1_2_3”?

Die Tabelle für die Nested Sets sieht wie folgt aus:

INSERT INTO `n_menu` (`itemId`, `parentId`, `name`, `href`) VALUES  
(1, 0, 'Startseite', ''),  
(2, 0, '1 Seite', 'seite_1'),  
(3, 2, '12 Seite', 'seite_1_2'),  
(4, 2, '123 Seite', 'seite_1_2_3');

Ich wollte die Inhalte über die itemId verknüpfen, aber wie finde ich dann den Inhalt für seite_1_2_3, abhängig von den Eltern?

Es läuft wohl auf Rekursion hinaus, aber wie?

mfg

  1. Hallo Malcolm,

    ich arbeite gerade an einem kleinen CMS für mich (so wie immer ;)) und ich habe es endlich geschafft, das ganze sauber umzusetzen.

    schön, Dich wieder zu lesen.

    Die Tabelle für die Nested Sets sieht wie folgt aus:

    INSERT INTO n_menu (itemId, parentId, name, href) VALUES

    (1, 0, 'Startseite', ''),
    (2, 0, '1 Seite', 'seite_1'),
    (3, 2, '12 Seite', 'seite_1_2'),
    (4, 2, '123 Seite', 'seite_1_2_3');

      
    das ist aber nicht die Tabellenstruktur, die für [Nested Sets](http://www.klempert.de/nested_sets/) erforderlich ist.  
      
      
      
    Freundliche Grüße  
      
    Vinzenz
    
    1. مرحبا

      schön, Dich wieder zu lesen.

      Freut mich auch wieder hier zu sein.

      das ist aber nicht die Tabellenstruktur, die für Nested Sets erforderlich ist.

      Ja ich weiss.
      Das ist eine Alternative zu den echten Nested Sets, eine, die ich verstehe und die bei mir funktioniert :)

      Ich habe mir zwischenzeitlich auch weiter Gedanken gemacht.

      Eine Idee wäre, die URI vorwärts und rückwärts checken (ich weiss, das klingt jetzt bissel komisch), und dann beide Resultate vergleichen, wenn sie übereinstimmen, mit dem letzten stück der URI die Inhalte holen.
      Sagen wir

      /de/auto/vw/golf

      Dann von "golf" zurückgehen, ob es Eltern gibt, bis /de/. Resultat der Schleife in einem String speichern.

      Dann nehme ich eine etwas abgeänderte version von $SERVER['REQUEST_URI'] und vergleiche beide Strings, wenn beide übereinstimmen, dann rufe ich den Content für "golf" auf.

      mfg

      1. مرحبا

        Eine Idee wäre, die URI vorwärts und rückwärts checken

        Und so funktioniert es auch.

        /de/auto/vw/golf

        Über $SERVER['REQUEST_URI'] das letzte stück nach dem letzten '/' auslesen und damit die ParentId von golf holen.

        Mit der ParentId ermittle ich dann in einer Schleife den nächst höheren Satz und baue mir rückwärts, ausgehend von golf, die URI auf, also

        golf/vw/auto/de/

        Dann Reverse ich das letzte stück und vergleiche es mit dem ersten String, wenn beide übereinstimmen, kann ich mit der ID von golf, die ich ja längst schon habe, die Inhalte holen.

        Problematisch wird es aber, wenn "golf" in der Kategorie "auto" und bspw. "freizeitaktivität" vorkommt.
        Wie kann ich das auch mit berücksichtigen?

        mfg

      2. Tach!

        das ist aber nicht die Tabellenstruktur, die für Nested Sets erforderlich ist.

        Ja ich weiss.
        Das ist eine Alternative zu den echten Nested Sets, eine, die ich verstehe und die bei mir funktioniert :)

        Nested Sets ist ein klar definierter Begriff. Du hast jedenfalls keine Nested Sets sondern ein Adjazenzlisten-Model oder auch Naive Tree genannt. Der Nachteil ist, dass du dich immer nur einen Schritt vor- oder zurückhangeln kannst und keine kompletten Teilstücke bekommst. Eine Möglichkeit ist Path Enumeration, also die (zusätzliche) Speicherung des kompletten Pfades, eine andere ist Nested Sets. Ein weiterer ist Closure Table.

        Vinzenz hatte das die Tage erst in die Runde geworfen. Zu allen genannten Begriffen findest du auf http://jdobbie.blogspot.com/2009/07/closure-trees.html eine Präsentation (ab Folie 48).

        dedlfix.

        1. مرحبا

          Nested Sets ist ein klar definierter Begriff. Du hast jedenfalls keine Nested Sets

          Erstmal danke für den Link, aber mein Problem ist nicht die Liste selbst, sondern wie ich die Inhalte der aufgerufenen Seite richtig identifiziere.

          Mein Model sieht wie folgt aus: http://test.kum-bochum.de/de/

          Und es funktioniert an sich auch, nur wie ich schon vermutet hatte knallt es, wenn die aufrufende URI doppelt in der DB vorkommt, was aber erwünscht ist.

          mfg

          1. Tach!

            Erstmal danke für den Link, aber mein Problem ist nicht die Liste selbst, sondern wie ich die Inhalte der aufgerufenen Seite richtig identifiziere.

            Am einfachsten wäre für deinen Fall die Path-Enumeration-Variante, allerdings nicht mit den IDs als Path sondern mit dem vollständigen Pfad der URL. Damit findest du zweifellos den richtigen Golf. Das geht, solange du wenig an der Struktur änderst, wobei Hinzufügen und Löschen noch die geringsten Probleme sind.

            dedlfix.

            1. مرحبا

              Am einfachsten wäre für deinen Fall die Path-Enumeration-Variante, allerdings nicht mit den IDs als Path sondern mit dem vollständigen Pfad der URL.

              Das denke ich auch. An sich wollte ich das unbedingt umgehen, aber so werde ich es machen.

              wobei Hinzufügen und Löschen noch die geringsten Probleme sind.

              Warum eigentlich? Insbesondere beim verschieben der Inhalte sehe ich keine Probleme, da ich in dem Fall nur zwei bis drei Werte in der Menu-Tabelle ändern müsste.
              Das ist das gute bei meinem Model, die ID müssen nicht zwingend fortlaufend sein.

              mfg

              1. Tach!

                wobei Hinzufügen und Löschen noch die geringsten Probleme sind.
                Warum eigentlich?

                Löschen ist klar, einfach alles LIKE eintrag% entfernen, erwischt auch dessen Kinder. Eintragen ist ebenso einfach, du kennst den Vorgänger und dessen Path, der zusammen mit dem neuen Eintrag den neuen Pfad ergibt.

                Insbesondere beim verschieben der Inhalte sehe ich keine Probleme, da ich in dem Fall nur zwei bis drei Werte in der Menu-Tabelle ändern müsste.

                Du verschiebst einen Zweig (also einen Eintrag mit all seinen Kindern), also muss vom gesamten Zweig die Path-Information angepasst werden.

                Das ist das gute bei meinem Model, die ID müssen nicht zwingend fortlaufend sein.

                Die interessieren ja auch nicht weiter. Hauptsächlich musst du anhand des Pfades suchen.

                dedlfix.

                1. مرحبا

                  beim verschieben der Inhalte

                  Du verschiebst einen Zweig (also einen Eintrag mit all seinen Kindern), also muss vom gesamten Zweig die Path-Information angepasst werden.

                  Wenn ich die Path-Enumeration-Variante so verwende, wie hier vorgeschlagen, dann wird das wirklich ein Akt.
                  Normalerweise müsste ich in der Menu-Tabelle nur den Elternknoten der zu verschiebenden Inhalte ändern, und die Kinder würden unabhängig bei den Eltern bleiben.

                  INSERT INTO `n_menu` (`itemId`, `parentId`, `name`, `href`) VALUES  
                  (1, 0, 'Startseite', ''),  
                  (2, 0, 'Wetter', 'Wetter'),  
                  (3, 0, 'Sport', 'sport'),  
                  (4, 3, 'Fussball', 'fussball'),  
                  (5, 3, 'Schwimmen', 'schwimmen');  
                  
                  

                  Wenn ich jetzt Sport verschiebe, würden die Kinder bei Sport bleiben. Bei der PEV-Variante müsste ich alle Kinder berücksichtigen und die Links umschreiben.

                  Ich muss wohl einfach noch ein bisschen weiter experimentieren, wie ich mit den Daten umgehe.

                  mfg

                  1. Tach!

                    Du verschiebst einen Zweig (also einen Eintrag mit all seinen Kindern), also muss vom gesamten Zweig die Path-Information angepasst werden.
                    Wenn ich die Path-Enumeration-Variante so verwende, wie hier vorgeschlagen, dann wird das wirklich ein Akt.

                    Du musst dich entscheiden, welchen Tod du sterben willst, entweder eine einfache Abfragemöglichkeit mit Aufwand beim Ändern oder umgekehrt.

                    dedlfix.

                    1. مرحبا

                      Wenn ich die Path-Enumeration-Variante so verwende, wie hier vorgeschlagen, dann wird das wirklich ein Akt.

                      Du musst dich entscheiden, welchen Tod du sterben willst, entweder eine einfache Abfragemöglichkeit mit Aufwand beim Ändern oder umgekehrt.

                      Mir kommt da noch eine Idee. Ich könte ja statt die URL komplett zu speichern, nur die Eltern-Ids jeden Zweigs speichern, also bei

                      /auto/vw/golf

                      statt

                      id  | URL  
                      ------------  
                      231 | '/auto/vw/golf'  
                        
                        
                      id  | URL  
                      ------------  
                      231 | '2,5,9'
                      

                      Und dann im Script daraus eine URL bauen. Ich müsste dann immer noch bei den Kindern hand anlegen, wenn ein Artikel verschoben wird, es wäre aber denke ich mal trotzdem einfacher.

                      mfg

                      1. Tach!

                        Mir kommt da noch eine Idee. Ich könte ja statt die URL komplett zu speichern, nur die Eltern-Ids jeden Zweigs speichern, also bei

                        Die hat den gravierenden Nachteil, dass du zuerst aus den IDs die URL ermitteln muss oder umgekehrt, damit du einen Vergleich von Request und Datenbankeintrag vornehmen kannst.

                        dedlfix.

                        1. مرحبا

                          Die hat den gravierenden Nachteil, dass du zuerst aus den IDs die URL ermitteln muss oder umgekehrt, damit du einen Vergleich von Request und Datenbankeintrag vornehmen kannst.

                          An sich war mein anfänglicher Ansatz schon richtig, ich hab nur bei der umsetzung gepatzt.

                          Ich muss die aufrufende URL rückwärts analysieren, allerdings nur mit dem letzten teil.

                          /auto/vw/golf

                          In diesem Fall könnte "golf" ein Kind von zwei Eltern sein, "freizeit" oder "vw".
                          Wenn "vw" gegeben ist, kann ich im Script prüfen, wessen Kind "vw" ist, usw..
                          Über die Details grübel ich noch.

                          mfg

                          1. مرحبا

                            korrekt, konnte es mit 2 einfachen Funktionen erledigen ;)

                            Muss nur noch einiges dazudichten, aber das Grundgerüst steht.
                            Ich habe unter HTML und unter CSS jeweils einen eintrag gemacht, der einen Identischen href-teil hat. Wenn nun eine dieser Seiten aufgerufen wird, bekomme ich ein Array mit allen Zweigen zurück, die auf den letzten teil der URL zutreffen.

                            /html-xhtml/html-elemente/div-elemente
                            /css/css-2/div-elemente

                            in beiden fällen bekomme ich ein Array zurück mit allen möglichen zweigen. Korrekt :)

                            Darauf kann ich jetzt weiter aufbauen.

                            mfg