Sven: Menü wird abgeschnitten

Hello,

ich habe keinen blassen Schimmer, wo der Fehler ist, und da ganze u.u. recht kompliziert erscheinen kann, habe ich auch gar nicht eine all- zugroße Aussicht auf Erfolg. Höchstwahrscheinlich ist es nur irgendein logischer Fehler.

Folgendes:

Ich habe ein Template, in dem ich die "ersetztenden stellen" für das Menü eingetragen habe:

...             <ul>             [LINKLIST:START]                 [LINKLIST:SINGLEITEM:START]<li><a href="[LINK:URL]" title="[LINK:TITLE]">[LINK:VALUE]</a></li>[LINKLIST:SINGLEITEM:END]                 [LINKLIST:SUBITEM:START]                 <li>                     <strong>[LINK:VALUE]</strong>                     <ul>[LINK:SUBLIST]</ul>                 </li>                 [LINKLIST:SUBITEM:END]             [LINKLIST:END]             </ul> ...

So, und jetzt habe ich eine Menüdatei, die so aussieht:

MENU STRUCTURE

Einzellink-Syntax:

SINGLEITEM [PARENT <X>]

URL = "URL des Links"

TITLE = "Titel des Links (title-Attribut)"

VALUE = "Linkanzeige (Inhalt vom Tag)"

Sublist-Syntax:

SUBLIST ID <X>

VALUE = "Überschrift der Sublist"

Durch dass jede Sublist eine ID bekommt, kann jedes

Singleitem mit dem Parent-Syntax der Sublist zugewiesen

werden. Hat ein Singleitem keinen Parent angegeben, gehört

es zum Hauptmenü und untersteht keinem Submenü.

Mehrfach verschachtelte Submenüs nicht gewollt (dennoch möglich).

Die Reihenfolge der Links in den entsprechenden Menüs erfolgt

anhand ihrer Notierung hier von oben nach unten (d.h. ein Link,

der hier in der Datei ganz oben steht, wird im erstellten Menü

ganz oben stehen).

SINGLEITEM URL = "start" TITLE = "Start" VALUE = "Start"

SINGLEITEM URL = "online" TITLE = "...online erreichbar? Technik und Sicherheit" VALUE = "...online?"

SUBLIST ID 1 VALUE = "SvensWebserver"

SINGLEITEM PARENT 1 URL = "i" TITLE = "Was hat's mit dem &quot;i&quot; auf sich?" VALUE = "Das besondere i..."

SINGLEITEM PARENT 1 URL = "intranet" TITLE = "Was gibt's auf dem Intranetserver zu sehen?" VALUE = "SvensWebserver grob betrachtet"

SINGLEITEM PARENT 1 URL = "http://intranet.[SERVER]" TITLE = "Der (Intranet)server ist zugriffsgeschützt" VALUE = "SvensWebserver besuchen"

SINGLEITEM URL = "toc" TITLE = "Was gibt's auf diesem Server zu sehen?" VALUE = "Inhalt auf diesem Server"

SINGLEITEM URL = "getpwd" TITLE = "Passwortanforderung erfolgt per E-Mail" VALUE = "Zugangspasswort anfordern"

SINGLEITEM URL = "http://validator.w3.org/check/referer" TITLE="Validate XHTML strict!" VALUE = "[TEMPLATE-SPECIALCONTENT:VALIDATE-XHTML]"

SINGLEITEM URL = "http://jigsaw.w3.org/css-validator/check/referer" TITLE="Validate CSS!" VALUE = "[TEMPLATE-SPECIALCONTENT:VALIDATE-CSS]"

EOF

Relativ einfach: Ein Menüpunkt wird also per SINGLEITEM eingeleitet, danach kommen die Parameter, und mit dem nächsten SINGLEITEM kommt der nächste Punkt. Ein SUBMENU ist genauso aufgebaut. Jedes Submenu hat eine ID, und wenn ein Singleitem unter einem Submenu erscheinen soll, dann schreibt man eben "SINGLEITEM PARENT [[ID]]". "SINGLEITEM PARENT 0", um den Eintrag dem Root unterzuordnen, ist nicht notwendig, das macht das System automatisch.

Der verarbeitende PHP-Auszug:

...     $menu_file     = file($my_menu_url); // <-- Inhalt der Datei siehe oben

// Menüdaten aus Menüfile gewinnen

$menu = array(); // darein wird das Menü gespeichert     $id   = -1;      // Id des aktuellen Eintrags (wird am Anfang gleich +1 addiert, daher -1)

foreach($menu_file as $line)     {         if(!preg_match('/[1]/', $line)) // Comments ausschließen         {             if(preg_match('/SINGLEITEM(?: PARENT (\d+))?/', $line, $parentmatch))             {                 $id++;                 // Menuitem mit Voreinstellungen füllen                 $menu[$id] = array(                     'typ'    => 'singleitem',                     'url'    => 'nicht definiert',                     'title'  => false,                     'value'  => 'nicht definiert',                     'parent' => 0);

if(isset($parentmatch[1]))                     // Parent speichern, wenn angegeben                     $menu[$id]['parent'] = $parentmatch[1];             }             elseif(preg_match('/SUBLIST ID (\d+)/', $line, $idmatch))             {                 $id++;

// Menüitem mit Voreinstellungen füllen                 $menu[$id] = array(                     'typ'    => 'sublist',                     'id'     => $idmatch[1],                     'name'   => 'nicht definiert',                     'parent' => 0);             }             elseif(preg_match('/([A-Z]+) ?= ?"(.+)"/', $line, $datamatch))             {                 $menu[$id][strtolower($datamatch[1])] = $datamatch[2];             }             elseif(preg_match('/EOF/', $line))                 continue;             else             {                 print "<p><b>Error:</b> bad syntax (menufile): $line</p>";             }         }     }

// Menü konstruieren     preg_match('/[LINKLIST:SINGLEITEM:START](.)[LINKLIST:SINGLEITEM:END]/', $template, $singleitem);     preg_match('/[LINKLIST:SUBITEM:START](.)[LINKLIST:SUBITEM:END]/s', $template, $subitem);     $menu_singleitem_pattern = $singleitem[1];     $menu_subitem_pattern    = $subitem[1];

function menu_format_singleitem($url, $title, $value)     {         global $menu_singleitem_pattern;         $r = str_replace('[LINK:URL]', $url, $menu_singleitem_pattern);         $r = str_replace('[LINK:TITLE]', $title, $r);         $r = str_replace('[LINK:VALUE]', $value, $r);         return $r;     }

function menu_format_subitem($value, $sublist)     {         global $menu_subitem_pattern;         $r = str_replace('[LINK:VALUE]', $value, $menu_subitem_pattern);         $r = str_replace('[LINK:SUBLIST]', $sublist, $r);         return $r;     }

$end_menu = menu_format(0);

function menu_format($parent)     {         global $menu;         $r = '';         foreach($menu as $item)         {             if($item['parent'] != $parent)                 continue;

if($item['typ'] == 'singleitem')                 $r .= menu_format_singleitem($item['url'], $item['title'], $item['value']);             elseif($item['typ'] == 'sublist')                 $r .= menu_format_subitem($item['value'], menu_format($item['id']));             else                 print "<p><b>Fehler:</b> Typ nicht feststellbar (system.php:menu_format()): $item[typ]</p>";         }         return $r;     }

// Menü in Template einbauen     $return = preg_replace('/[LINKLIST:START].*[LINKLIST:END]/s', $end_menu, $template); ...

Ok, so kompliziert ist es eigentlich gar nicht. Fakt ist: Nach den SINGLEITEM's, die dem einen Submenu untergeordnet sind, wird kein einziger Menüeintrag mehr angezeigt. Woran kann das liegen? Ich ent- decke den Fehler nicht :[

Gruß,

Sven


  1. #\s ↩︎

  1. Moin Sven,

    »» Hello,

    ich habe keinen blassen Schimmer, wo der Fehler ist, und da ganze u.u.
    recht kompliziert erscheinen kann, habe ich auch gar nicht eine all-
    zugroße Aussicht auf Erfolg. Höchstwahrscheinlich ist es nur irgendein

    zunächst einmal ist dein Posting viel zu lang. Was glaubst Du wer sich durch den Quelltext kämpft?

    Hast Du mal versucht zu debuggen. Also, bis wohin geht es und ab
    wann nicht mehr?

    Grüsse
    Mike

    --
    Freunde kommen und gehen. Feinde sammeln sich an.
    1. Moin Mike,

      ich habe keinen blassen Schimmer, wo der Fehler ist, und da ganze u.u.
      recht kompliziert erscheinen kann, habe ich auch gar nicht eine all-
      zugroße Aussicht auf Erfolg. Höchstwahrscheinlich ist es nur irgendein
      zunächst einmal ist dein Posting viel zu lang.

      Wohl oder übel.

      Was glaubst Du wer sich durch den Quelltext kämpft?

      Gegenfrage: Was glaubst du, warum ich das von dir zitierte geschrieben
      habe?

      Hast Du mal versucht zu debuggen. Also, bis wohin geht es und ab
      wann nicht mehr?

      Das ganze Script läuft locker, das ist kein Problem (dafür gibt's ja
      die PHP-Fehlermeldungchen). Oder was meinst du jetzt mit "debuggen"?

      Kein Syntaxfehler oder sowas. Irgendeine Art logischer Fehler. Ja,
      ich bin das ganze schon mal im Kopf durchgegangen und bin auf keinen
      geraden Ast gekommen. Meines erachtens müsste es so gehen, wie es
      gehen soll.

      Gruß,

      Sve

      1. Moin Sven,

        Das ganze Script läuft locker, das ist kein Problem (dafür gibt's ja
        die PHP-Fehlermeldungchen). Oder was meinst du jetzt mit "debuggen"?

        mit debuggen meine ich; Steps einbauen. Da das Script sehr umfangreich ist, solltest Du prüfen bis wohin es richtig läuft und ab wann es nicht mehr tut was es soll.

        Grüsse
        Mike

        --
        Freunde kommen und gehen. Feinde sammeln sich an.
        1. Hallo,

          ok, alles jetzt also erheblich einfacher. Schön, folgendes Array haben
          wir in $menu gespeichert:

          Array
          (
              [0] => Array
                  (
                      [typ] => singleitem
                      [url] => start
                      [title] => Start
                      [value] => Start
                      [parent] => 0
                  )

          ...

          [2] => Array
                  (
                      [typ] => sublist
                      [id] => 1
                      [name] => nicht definiert
                      [parent] => 0
                      [value] => SvensWebserver
                  )

          ...

          [5] => Array
                  (
                      [typ] => singleitem
                      [url] => http://intranet.[SERVER]
                      [title] => Der (Intranet)server ist zugriffsgeschützt
                      [value] => SvensWebserver besuchen
                      [parent] => 1
                  )

          [6] => Array
                  (
                      [typ] => singleitem
                      [url] => toc
                      [title] => Was gibt's auf diesem Server zu sehen?
                      [value] => Inhalt auf diesem Server
                      [parent] => 0
                  )

          ....

          )

          Die meisten Inhalte des Arrays sind egal, es geht jetzt lediglich um
          [typ] und [parent]. Mit dem ganzen wird jetzt folgende Funktion ge-
          füttert, die ich jetzt mit ein paar Comments bestückt habe, die das
          Problem verdeutlichen:

          print menu_format(0);

          function menu_format($parent)
              {
                  global $menu;
                  $r = '';
                  print 'menu_format aufgerufen<br>';
                  foreach($menu as $item)
                  {
                      if($item['parent'] != $parent)
                      {
                          print "Keine Parent-Zustimmung: Content: $item[value]. Parent: $item[parent]. Parent sollte sein: $parent<br>";
                          continue;
                      }
                      else
                      {
                          print "Parent-Zustimmung: $parent muss sein und ist $item[parent]. Content: $item[value]<br>";
                      }

          if($item['typ'] == 'singleitem')
                          $r .= menu_format_singleitem($item['url'], $item['title'], $item['value']);
                      elseif($item['typ'] == 'sublist')
                      {
                          print "SUBMENU FOUND: [Parent jetzt noch $parent]<br>";
                          $submenu = menu_format($item['id']);
                          print "SUBMENU created<br>";
                          $r .= menu_format_subitem($item['value'], $submenu);
                          print "SUBMENU written [Parent jetzt $parent]<br>";
                          continue;
                      }
                      else
                          print "<p><b>Fehler:</b> Typ nicht feststellbar (system.php:menu_format()): $item[typ]</p>";
                  }
                  return $r;
              }

          jetzt schauen wir uns mal diese "Comments", die überall in dieser
          Funktion sind (print "...";) an:

          menu_format aufgerufen
          Parent-Zustimmung: 0 muss sein und ist 0. Content: Start
          Parent-Zustimmung: 0 muss sein und ist 0. Content: ...online?
          Parent-Zustimmung: 0 muss sein und ist 0. Content: SvensWebserver
          SUBMENU FOUND: [Parent jetzt noch 0]
          menu_format aufgerufen
          Keine Parent-Zustimmung: Content: Start. Parent: 0. Parent sollte sein: 1
          Keine Parent-Zustimmung: Content: ...online?. Parent: 0. Parent sollte sein: 1
          Keine Parent-Zustimmung: Content: SvensWebserver. Parent: 0. Parent sollte sein: 1
          Parent-Zustimmung: 1 muss sein und ist 1. Content: Das besondere i...
          Parent-Zustimmung: 1 muss sein und ist 1. Content: SvensWebserver grob betrachtet
          Parent-Zustimmung: 1 muss sein und ist 1. Content: SvensWebserver besuchen
          Keine Parent-Zustimmung: Content: Inhalt auf diesem Server. Parent: 0. Parent sollte sein: 1
          Keine Parent-Zustimmung: Content: Zugangspasswort anfordern. Parent: 0. Parent sollte sein: 1
          Keine Parent-Zustimmung: Content: [TEMPLATE-SPECIALCONTENT:VALIDATE-XHTML]. Parent: 0. Parent sollte sein: 1
          Keine Parent-Zustimmung: Content: [TEMPLATE-SPECIALCONTENT:VALIDATE-CSS]. Parent: 0. Parent sollte sein: 1
          SUBMENU created
          SUBMENU written [Parent jetzt 0]

          Und hier hört es schlagartig auf, obwohl das Array noch eine ganze
          Menge weiterer Elemente hat, die von der Schleife ___nicht___ mehr
          durchlaufen werden.

          was ist der Grund?

          Gruß,

          Sven

          1. Moin Sven,

            was ist der Grund?

            schon wieder kilo weise Quelltext, ich schaue mir das morgen an.

            Grüsse
            Mike

            --
            Freunde kommen und gehen. Feinde sammeln sich an.
            1. Hello,

              so, der Grund ist jetzt klar:

              function menu_format($parent)
                  {
                      global $menu;
                      $r = '';
                      print 'menu_format aufgerufen<br>';
                      foreach($GLOBALS['menu'] as $item)
                      {
                              ...
                              $submenu = menu_format($item['id']);
                              ...
                      }
                      return $r;
                  }

              Ich habe die Funktion menu_format(), die sozusagen rekursiv ist, also
              in der Funktion wird die Funktion wieder aufgerufen, usw..

              In der Funktion globalisiere ich am Anfang $menu und beginne gleich
              eine foreach()-schleife. hierbei wird $menu geresettet und dann
              durchgegangen. Bekanntlich ist ja

              reset ($arr);
              while (list(, $value) = each ($arr)) {
                  echo "Wert: $value<br>\n";
              }

              das gleiche wie dasda:

              foreach ($arr as $value) {
                  echo "Wert: $value<br>\n";
              }

              Rufe ich jetzt also in dieser Schleife wieder die Funktion auf, wird
              die globalisierte Variable $menu wieder geresettet und neu durch-
              gegangen. Ist der Durchgang fertig und die "Vaterfunktion" macht den
              nächsten Durchlauf, ist die durchgegangene Variable ja bereits ge-
              resettet und er glaubt dann irgendwie, er sei bereits das ganze Array
              durchgegangen.

              Abhilfe bringt folgendes:

              function menu_format($parent)
                  {
                      $r = '';
                      print 'menu_format aufgerufen<br>';
                      foreach($GLOBALS['menu'] as $item)
                      {
                      .....

              hier greife ich jeweils direkt auf die $GLOBALS zu. In anderen
              Variablenräumen kann ich $menu nun also nach meinem Belieben resetten
              oder sonstwas machen, und es hat keine Auswirkungen auf meine schleife
              hier.

              :)

              Gruß,

              Sven