Engin: Regexp, mod_rewrite und $_SERVER["REQUEST_URI"], Sinn und Unsinn

Ave!

Hab da ein indirektes Problem, ich bastle gerade ein wenig mit mod_rewrite rum, Ziel ist die URI Struktur einheitlich aussehen zu lassen.

Auf meinem Server hab ich 5 Verzeichnisse mit allen Dateien, für den User und auch für Suchmaschinen soll es aber so aussehen, als käme alles aus einem Verzeichnis, soweit klappt alles auch.
Nur, jetzt muss ich alle regexp, die dafür sorgen, das die Aktuelle Seite sich nicht selbst verlinkt ändern und mit $_SERVER["REQUEST_URI"] statt $_SERVER["SCRIPT_NAME"] arbeiten, meine frage, kann ich da was falsch machen?

$nav = '<li><a href="/hauptverzeichnis/datei">Link1</a></li>';  
$pattern = '#<a href="'.$_SERVER["REQUEST_URI"].'">(.+?)</a>#';  
echo preg_replace($pattern,'<em>$1</em>',$nav);

Wie gesagt, funktionieren tut es mittlerweile (nach geschlagenen 5 Stunden).

Grüße aus H im R an alle,
  Primus Enginus*

  1. Hi,

    Nur, jetzt muss ich alle regexp, die dafür sorgen, das die Aktuelle Seite sich nicht selbst verlinkt ändern [...], meine frage, kann ich da was falsch machen?

    Ja - bspw. mit Regexp arbeiten.

    $nav = '<li><a href="/hauptverzeichnis/datei">Link1</a></li>';

    $pattern = '#<a href="'.$_SERVER["REQUEST_URI"].'">(.+?)</a>#';
    echo preg_replace($pattern,'<em>$1</em>',$nav);

      
    Wozu der replace-Kaese?  
      
    Abgesehen davon, dass eine Seite i.a.R. nicht auf sich selbst verlinken sollte, du also eher <a> entfernen als <em> hinzufuegen solltest - wozu denn hier erst mal was definieren, um es dann mit regulaeren Ausdruecken wieder zu ersetzen?  
      
    Warum nicht einfach so:  
      
    if($aktuelleSeite == xyz) {  
      // Ausgabe des reinen Textes fuer den Navigationspunkt xyz  
    }  
    else {  
      // Ausgabe des Links, der die Seite verlinkt, mit Linktext xyz  
    }  
      
      
    Und da das wohl fuer mehr als einen Link passieren soll, bietet sich eine Schleife ueber alle in der Navigation verwendeten Links an - bspw. also eine Schleife ueber ein Array, das alle Linkziele und -texte enthaelt.  
      
    MfG ChrisB
    
    1. Ave ChrisB!

      Wozu der replace-Kaese?

      Meine erste Idee, die Aktuelle Seite zu entlinken war wie du unten vorschlägst, dann hatte Ingo das replace schnipsel gepostet und das gefiel mir besser.

      Abgesehen davon, dass eine Seite i.a.R. nicht auf sich selbst verlinken sollte, du also eher <a> entfernen als <em> hinzufuegen solltest - wozu denn hier erst mal was definieren, um es dann mit regulaeren Ausdruecken wieder zu ersetzen?

      Das <em> dient nur der formatierung.

      Warum nicht einfach so:
      if($aktuelleSeite == xyz) {
        // Ausgabe des reinen Textes fuer den Navigationspunkt xyz
      }
      else {
        // Ausgabe des Links, der die Seite verlinkt, mit Linktext xyz
      }
      Und da das wohl fuer mehr als einen Link passieren soll, bietet sich eine Schleife ueber alle in der Navigation verwendeten Links an - bspw. also eine Schleife ueber ein Array, das alle Linkziele und -texte enthaelt.

      <homer>NEIN</homer>, schon wieder denken, aber das klingt auch ganz gut, ich werde es gleich mal probieren.
      Zumal, da die Navigation auf 2 Ebenen läuft, (Ober/Unterkategorie) hatte ich mich eh die ganze Zeit gefragt, wie ich von beiden Ebenen die Links "entlinke", so müsste ich es schaffen.

      Danke für immer wieder gute Inspirationen!

      Darf ich dir http://kultdose.de schenken?  :)
      Mir fällt nichts ein, was ich da machen kann.

      Grüße aus H im R an ChrisB,
        Primus Enginus*

    2. Ave ChrisB!

      Danke für diesen Vorschlag! :) Ich hab ein Array gebaut....:-)).....:-)))[1]

        
      error_reporting(E_ALL);  
        
      $aktuelle_seite = $_SERVER["REQUEST_URI"]; /* um den komm ich irgendwie nicht rum */  
        
        $navi_links = array("/verz1/dat1", "/verz2/dat2", "/verz3/dat3", "/verz4/dat4");  
        
        foreach($navi_links as $neue_links)  {  
        
           if($aktuelle_seite == $neue_links) {  
        
       $neues_menu[] = $neue_links."<br />";  
        
            }  
           else {  
        
       $neues_menu[] = '<a href="'.$neue_links.'">'.$neue_links.'</a><br />';  
               }  
        }  
        
      print_r($neues_menu);
      

      Jetzt muss ich nur noch verstehen, wie ich aus dieser Typischen Array Ausgabe rauskomme, da blick ich irgendwie nicht so durch.
      Ausgerechnet das gibt es nicht in Deutsch.

      Hab ich das jetzt soweit richtig? Funktioniert so wie es soll, Aktuelle Seite wird entlinkt und alle anderen werden verlinkt, auch die Reihenfolge stimmt (auch beim Seitenwechsel).

      Grüße aus H im R an ChrisB,
        Primus Enginus*
      [1] Das ist mein erstes mal :-))

      1. Hi,

        Jetzt muss ich nur noch verstehen, wie ich aus dieser Typischen Array Ausgabe rauskomme, da blick ich irgendwie nicht so durch.
        Ausgerechnet das gibt es nicht in Deutsch.

        print_r/var_dump eignen sich vornehmlich fuer Kontrollausgaben.

        Wenn du alle Elemente eines Arrays ausgeben willst - dann durchlauefst du es halt (noch mal) mit einer Schleife - foreach, oder for bei nummerisch indiziertem Array.

        In deinem Fall brauchst aber vermutlich gar keine zweite Schleife - du kannst dir doch schon in der ersten den HTML-Code, den du letztendlich ausgeben willst, in einer Variablen zusammenbauen.

        $menuOutput = '';
        foreach(...) {
          $menuOutput .= '[HTML-Code fuer aktuellen Menuepunkt]';
        }

        Und irgendwo spaeter, wo dein Menue dann in der Seite stehen soll, gibst du dann $menuOutput einfach aus.

        (Wenn das ganze bspw. eine Liste werden soll - dann initialisierst du $menuOutput vor der Schleife mit '<ul id="menue">', haengst dann in der Schleife deine '<li><a>...</a></li>' an, und nach der Schleife noch ein schliessendes '</ul>' - et voila :-))

        Hab ich das jetzt soweit richtig?

        Mit $_SERVER["REQUEST_URI"]; solltest du vorsichtig sein, das muss nicht unbedingt das enthalten, auf das du vergleichen willst - wenn die Seite bspw. mit GET-Parametern angefordert wird, dann haengt der Query-String am Seitennamen in $_SERVER["REQUEST_URI"] ebenfalls mit dran. Da muesstest du aus dem Wert also ggf. vorher noch den relevanten Part ausschneiden.

        MfG ChrisB

        1. Ave ChrisB!

          $menuOutput = '';
          foreach(...) {
            $menuOutput .= '[HTML-Code fuer aktuellen Menuepunkt]';
          }
          Und irgendwo spaeter, wo dein Menue dann in der Seite stehen soll, gibst du dann $menuOutput einfach aus.

          Du machst mich noch fertig! Ich hatte gerade geschnallt, das ich foreach 2 mal anwenden kann, das wollte ich vor 20 Minuten bekannt geben. :)

          (Wenn das ganze bspw. eine Liste werden soll - dann initialisierst du $menuOutput vor der Schleife mit '<ul id="menue">', haengst dann in der Schleife deine '<li><a>...</a></li>' an, und nach der Schleife noch ein schliessendes '</ul>' - et voila :-))

          Ich hab´s zwar hingekriegt, aber ohne initialisieren, ich weiß ja nicht mal was das heißt. :)

          Aber es Funzt[TM], und sieht auch viel übersichtlicher aus als mit dem replacen.

          <?php  
            
          $aktuelle_seite = $_SERVER["REQUEST_URI"];  
            
          $navi_links = array("/verz1/dat1", "/verz2/dat2", "/verz3/dat3", "/verz4/dat4");  
            
          $ListeBauen = '';  
            
             foreach($navi_links as $neue_links) {  
            
             if($aktuelle_seite == $neue_links) {  
           $ListeBauen .= "<li><em>$neue_links</em></li>";  
            }  
             else {  
           $ListeBauen .= "<li><a href=\"$neue_links\">$neue_links</a></li>";  
                   }  
             }  
            
          $menuOutput = '<ul id="ausklapp_navi_2" class="klapp_navi_klasse">'.$ListeBauen.'</ul>';  
            
          echo $menuOutput;  
            
          ?>
          

          Mit $_SERVER["REQUEST_URI"]; solltest du vorsichtig sein, das muss nicht unbedingt das enthalten, auf das du vergleichen willst - wenn die Seite bspw. mit GET-Parametern angefordert wird, dann haengt der Query-String am Seitennamen in $_SERVER["REQUEST_URI"] ebenfalls mit dran. Da muesstest du aus dem Wert also ggf. vorher noch den relevanten Part ausschneiden.

          Das muss ich jetzt erstmal verstehen.
          Das $_SERVER["REQUEST_URI"] ist ins Spiel gekommen, weil ich mit mod_rewrite die URL umschreibe, dadurch fällt $_SERVER["SCRIPT_NAME"] schon mal weg, gibt es noch eine andere Alternative?
          Mir ist nur wichtig, das in der Adressleiste des Browsers das .php weg ist.

          Grüße aus H im R an ChrisB,
            Primus Enginus*

          1. Hi,

            Ich hab´s zwar hingekriegt, aber ohne initialisieren, ich weiß ja nicht mal was das heißt. :)

            Das heisst es:

            $ListeBauen = '';

            Wenn du das nicht machen wuerdest, wuerdest du beim ersten Schleifendurchlauf hier

            $ListeBauen .= "<li><em>$neue_links</em></li>";

            die Meldung kriegen, dass $ListeBauen nicht definiert ist.
            Also alles richtig gemacht :-)

            Das $_SERVER["REQUEST_URI"] ist ins Spiel gekommen, weil ich mit mod_rewrite die URL umschreibe, dadurch fällt $_SERVER["SCRIPT_NAME"] schon mal weg, gibt es noch eine andere Alternative?

            Nun ja, wenn du mod_rewrite nutzt, dann benutzt du ja vermutlich gar keine Links mehr, die GET-Parameter enthalten - in dem Falle ist also alles OK.
            (Und wenn mal irgendjemand eine Seite "von Hand" aufruft, und dabei GET-Parameter anhaengt, um zu sehen, was passiert - dann tritt halt der "worst case" ein, dass in diesem Falle der aktuelle Menuepunkt nicht hervorgehoben wird ...)

            MfG ChrisB

            1. Ave ChrisB!

              $ListeBauen .= "<li><em>$neue_links</em></li>";

              die Meldung kriegen, dass $ListeBauen nicht definiert ist.
              Also alles richtig gemacht :-)

              Yuhoo! Endlich mal etwas "halbwegs" alleine gebacken gekriegt, und dann noch mit array. Beim anblick dieses Wortes lief es mir bis Heute immer Eiskalt den Rücken runter. :)

              Nun ja, wenn du mod_rewrite nutzt, dann benutzt du ja vermutlich gar keine Links mehr, die GET-Parameter enthalten - in dem Falle ist also alles OK.

              Dann kann es endlich weiter gehen.

              (Und wenn mal irgendjemand eine Seite "von Hand" aufruft, und dabei GET-Parameter anhaengt, um zu sehen, was passiert - dann tritt halt der "worst case" ein, dass in diesem Falle der aktuelle Menuepunkt nicht hervorgehoben wird ...)

              Damit kann ich leben. :)

              Vielen Dank für alles.

              Grüße aus H im R an ChrisB,
                Primus Enginus*

          2. Hello,

            Das $_SERVER["REQUEST_URI"] ist ins Spiel gekommen, weil ich mit mod_rewrite die URL umschreibe, dadurch fällt $_SERVER["SCRIPT_NAME"] schon mal weg, gibt es noch eine andere Alternative?
            Mir ist nur wichtig, das in der Adressleiste des Browsers das .php weg ist.

            Du solltest genauso wenig $_SERVER['REQUEST_URI'] wie $_SERVER['PHP_SELF'] direkt benutzen für den Selbstbezug im action-Attribut des Forms.

            Du solltest Dir eine Funktion schreiben, die diesen Wert erzeugt aus _sicheren_ Daten. Die kannst Du dann anstelle von irgendwelchem Gebastel dort einbinden.

            $form = '';
               $form .= "<form action="".meine_url_funktion($seite)"." method="post">\r\n";
               $form .= ....usw.

            Dann hast Du das Gehampel mit der Umsetzung auch zentralisiert auf diese Funktion und musst Dich nicht später nochmal durch die gesamten Scripte wühlen, wenn Du doch nochmal etwas ändern willst an den Paramertern.

            Die beiden Variablen $_SERVER['REQUEST_URI'] und $_SERVER['PHP_SELF'] sind aber bekanntermaßen unsicher, da sie beim Response-Request-Ping-Pong durch den Client verändert werden können.

            Das öffnet eine Lücke für Cross Site Scripting und "Phishing".

            Ein harzliches Glückauf

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Hi,

              Du solltest genauso wenig $_SERVER['REQUEST_URI'] wie $_SERVER['PHP_SELF'] direkt benutzen für den Selbstbezug im action-Attribut des Forms.

              Wo ist denn hier ein Formular im Spiel?

              Du solltest Dir eine Funktion schreiben, die diesen Wert erzeugt aus _sicheren_ Daten. Die kannst Du dann anstelle von irgendwelchem Gebastel dort einbinden.

              Ja, wenn's zu Formularen kommt, dann schon.

              Das öffnet eine Lücke für Cross Site Scripting und "Phishing".

              Jetzt verwirr mir das Kerlchen nicht ... was die Links angeht, ist das durch die Hinterlegung der ausgegebenen Werte im Array hinreichend sicher.

              MfG ChrisB

              1. Hello,

                Jetzt verwirr mir das Kerlchen nicht ... was die Links angeht, ist das durch die Hinterlegung der ausgegebenen Werte im Array hinreichend sicher.

                Ach, Engin ist schon ganz fit, auch wenn er sein Licht immer unter den Scheffel stellt.

                Ein harzliches Glückauf

                Tom vom Berg

                --
                Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
              2. Ave ChrisB, hi Tom,

                Jetzt verwirr mir das Kerlchen nicht ... was die Links angeht, ist das durch die Hinterlegung der ausgegebenen Werte im Array hinreichend sicher.

                Hab gerade den Satz "bspw. also eine Schleife ueber ein Array, das alle Linkziele und -texte enthaelt", das mit den Link-texten. :) Hab ich auch direkt umgesetzt.

                Jetzt ist das Script Geil! Jetzt kann ich mir viele Navis in eine Datei packen und via require überall mit echo ausgeben.

                Meine bisherige Lösung bestand aus...ach ich fang am besten gar nicht erst an das zu erzählen, rund 8 Dateien, die nur zum Auslagern von Navigationen gedacht waren. :)

                Dafür ist doch require gedacht oder wäre ich hier mit include besser bedient?

                Grüße aus H im R an ChrisB,
                  Primus Enginus*

                1. Hello Engin,

                  Dafür ist doch require gedacht oder wäre ich hier mit include besser bedient?

                  Ein kontrolliertes include() wäre dann schon besser, denn bei einem Fehler von Require() würde das Script abgebrochen werden. Das willst Du aber gar nicht unbedingt. Es könnte ja ein Standardlink in der Navi stehen (z.B. aufs Impressum), der durch ein erfolgreiches include() einfach überschrieben wird.

                  Ein harzliches Glückauf

                  Tom vom Berg

                  --
                  Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
                  1. Ave Tom!

                    Ein kontrolliertes include() wäre dann schon besser, denn bei einem Fehler von Require() würde das Script abgebrochen werden. Das willst Du aber gar nicht unbedingt. Es könnte ja ein Standardlink in der Navi stehen (z.B. aufs Impressum), der durch ein erfolgreiches include() einfach überschrieben wird.

                    Noch besser, include() hab ich schon in allen Dateien stehen, dann kann ich das so lassen und brauch nur eine Datei anpassen. :)

                    Danke für die Info.

                    Grüße aus H im R an Tom,
                      Primus Enginus*

                2. Hi,

                  Dafür ist doch require gedacht oder wäre ich hier mit include besser bedient?

                  Der einzige Unterschied zwischen beiden ist, dass require das komlette Script abbricht, wenn es die Datei, die es einbinden soll, nicht findet - waehrend include sich mit 'ner kleinen Meldung abgibt, und danach alles weiter laeuft.
                  Willst du, dass das Script weiterlaeuft, wenn die Navigation nicht eingebunden werden kann? Wenn ja, nimm include, sonst require.

                  (Normalerweise und wenn man nicht zu sehr mit seinen Dateien rumpfuscht, und auf dem Server nichts Amok laeuft, tritt der Fall, dass statisch angegebene einzubindende Dateien nicht gefunden/geoeffnet werden koennen, wohl kaum ein ... also kein Grund, sich darueber allzu lange den Kopf zu zerbrechen.)

                  MfG ChrisB

                  1. Hello,

                    (Normalerweise und wenn man nicht zu sehr mit seinen Dateien rumpfuscht, und auf dem Server nichts Amok laeuft, tritt der Fall, dass statisch angegebene einzubindende Dateien nicht gefunden/geoeffnet werden koennen, wohl kaum ein ... also kein Grund, sich darueber allzu lange den Kopf zu zerbrechen.)

                    Das setzt voraus, dass die Daten während der Laufzeit nicht verändert werden, also nur gelesen werden. Denn sonst sind include() und require() ohnehin nur Schlampereien und nicht für den Multiuserbetrieb geeignet.

                    Ein harzliches Glückauf

                    Tom vom Berg

                    --
                    Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
                    1. Hi,

                      Das setzt voraus, dass die Daten während der Laufzeit nicht verändert werden, also nur gelesen werden.

                      Was denkst, *wie* dynamisch Engin seine Navigation haben moechte - selbst-modifizierend ...?

                      MfG ChrisB

                      1. Hello,

                        Das setzt voraus, dass die Daten während der Laufzeit nicht verändert werden, also nur gelesen werden.

                        Was denkst, *wie* dynamisch Engin seine Navigation haben moechte - selbst-modifizierend ...?

                        Genau. Es entsteht ein usergesteuertes Navigationssystem, auch CMS genannt.

                        Jedenfalls sehe ich das kommen, wenn Engin so weitermacht.
                        Und dann wird das vermutlich das erste am Markt sein, das valides XHTML ausspuckt :-)

                        Ein harzliches Glückauf

                        Tom vom Berg

                        --
                        Nur selber lernen macht schlau
                        http://bergpost.annerschbarrich.de
                        1. Ave Tom!

                          Genau. Es entsteht ein usergesteuertes Navigationssystem, auch CMS genannt.
                          Jedenfalls sehe ich das kommen, wenn Engin so weitermacht.
                          Und dann wird das vermutlich das erste am Markt sein, das valides XHTML ausspuckt :-)

                          Jetzt ist es doch aufgeflogen. :)
                          Meine Sitemap war in der Tat Dynamisch, nur jetzt, mit der umstruktierung der gesamten Seite muss ich mir was neues überlegen. :)

                          <?php  
                          $ordner = "../einVerzeichnis";  
                          $dir_handle = opendir($ordner);  
                          while ($filename = readdir($dir_handle))  
                          {  
                              if ($filename != '..' && $filename != '.' && $filename != 'dateien-navi')  
                              {  
                            
                          $new_filename = str_replace(".php", "", $filename);  
                          $noch_new_filename = str_replace("-", " ", $new_filename);  
                            
                           echo ' <li><a href="'.$ordner.$new_filename.'">'.ucwords($noch_new_filename)."</a></li>\n";  
                            
                              }  
                          }  
                          closedir($dir_handle);  
                          ?>
                          

                          Aus der Traum von der Dynamischen Sitemap. :(

                          Grüße aus H im R an Tom,
                            Primus Enginus*

                  2. Ave ChrisB!

                    (Normalerweise und wenn man nicht zu sehr mit seinen Dateien rumpfuscht, und auf dem Server nichts Amok laeuft, tritt der Fall, dass statisch angegebene einzubindende Dateien nicht gefunden/geoeffnet werden koennen, wohl kaum ein ... also kein Grund, sich darueber allzu lange den Kopf zu zerbrechen.)

                    Dann verhalte ich mich meinem Newb Status entsprechend, ich verwende include()[1]. :)

                    Danke.

                    Grüße aus H im R an ChrisB,
                      Primus Enginus*
                    [1] Sicher ist Sicher