Caro: .htaccess, header()-Weiterleitung und Session-Variable

Hallo, alle zusammen!

Ich hab da ein recht seltsames Verhalten meines lokalen Webservers und/oder meiner Skripte. Es gibt einen praktikablen Workaround, das ist nicht das Thema. Aber anscheinden habe ich irgendeine grundlegende Funktionalität von PHP Sessions oder des .htaccess - Files nicht richtig verstanden und möchte diese Bildungslücke gerne schließen ...

Zunächst eine kurze Beschreibung zum dynamischen Aufbau meines Webauftrittes:
Der Auftritt läuft komplett über die index.php. Bei Anklicken eines Menüpunktes wird Variable $cont, die festlegt, welcher Content eingebunden wird, per GET weitergegeben. Diese Variable dann in einer Session abgespeichert, damit man sich innerhalb eines Menüpunktes bewegen kann. Der Auftritt liegt nicht in der Document-Root sondern in /unterverzeichnis.

Meine .htaccess in der Document-Root ruft bei Fehler 404 nun die Datei fehler.php (ebenfalls in der Document-Root) auf, und Diese enthält folgende Zeile:

header("Location: unterverzeichnis/index.php?cont=fehler");

So, das Problem: wenn ich nun http://localhost/unterverzeichnis/index.php ohne Parameter aufrufe, zeigt sich die Fehlerseite und das liegt daran, daß in der Session die Variable cont=fehler gesetzt ist.

Ich habe ein wenig mit der fehler.php rumgespielt und folgende Ergebnisse erhalten:

header("Location: unterverzeichnis/test.php?cont=fehler");

Die Seite index.php wird gelaten, $_SESSION['cont']='fehler', $_GET['cont']=NULL,

header("Location: unterverzeichnis/index.php?cont=hund");

Die Seite index.php wird gelaten, $_SESSION['cont']='hund', $_GET['cont']=NULL,

(und ich bin mir sehr sicher, daß ich die Variable $hund nirgends sonst verwendet habe ...)

header("Location: unterverzeichnis/index.php");

Die Seite index.php wird gelaten, $_SESSION['cont']=NULL, $_GET['cont']=NULL,

statt header() eine Textausgabe:

Die Seite index.php wird gelaten, $_SESSION['cont']=NULL, $_GET['cont']=NULL, keine Textausgabe

Ergebnis: die Weiterleitung wird nicht ausgeführt (es wird immer die index.php geladen), aber die Variable cont wird ausgelesen, und zwar wird sie nicht per $GET übertragen sondern direkt in die SESSION, die zu diesem Zeitpunkt zwar vom vorherigen Aufruf noch besteht, aber noch nicht einmal gestartet ist, eingelesen.

Wenn ich statt der header()-Weiterleitung eine HTML-Weiterleitung (per <meta refresh>) verwende, funktioniert alles, wie es soll (das ist auch die Lösung, die ich nun verwende).

Ich verstehe es nicht, hat jemand von Euch eine Erklärung?

Hoffnungsvoll, Caro

  1. echo $begrüßung;

    Meine .htaccess in der Document-Root ruft bei Fehler 404 nun die Datei fehler.php (ebenfalls in der Document-Root) auf, und Diese enthält folgende Zeile:

    header("Location: unterverzeichnis/index.php?cont=fehler");

    Das sind zwei Fehler auf einmal. Zum einen schreibt HTTP vor, dass der Location-Header eine absolute URL (http://...) liefert und keine relative. Zum anderen ist das vorgesehene Mittel bei Abruf einer nicht vorhandenen Ressource der Statuscode 404 und keine Weiterleitung (302) auf eine Ressource, die du vermutlich mit Statuscode 200 auslieferst. Suchmaschinen werden es dir danken, wenn sie die richtigen Statuscodes bekommen und müssen nicht zu obskuren Mitteln greifen, um rauszufinden, wie sich dein Server bei 404-Fehlern verhält.

    Wenn du das beherzigst, hast du kein Weiterleitungsproblem mehr.

    header("Location: unterverzeichnis/index.php?cont=hund");

    Die Seite index.php wird gelaten, $_SESSION['cont']='hund', $_GET['cont']=NULL,
           (und ich bin mir sehr sicher, daß ich die Variable $hund nirgends sonst verwendet habe ...)

    Eine Variable $hund spielt hier auch keine Rolle. Du verwendest den Wert "hund".

    Ergebnis: die Weiterleitung wird nicht ausgeführt (es wird immer die index.php geladen), aber die Variable cont wird ausgelesen, und zwar wird sie nicht per $GET übertragen sondern direkt in die SESSION, die zu diesem Zeitpunkt zwar vom vorherigen Aufruf noch besteht, aber noch nicht einmal gestartet ist, eingelesen.

    Das passiert nicht einfach so. PHP verändert keine Session-Variablen ohne Aufforderung durch ein Script.

    Ich verstehe es nicht, hat jemand von Euch eine Erklärung?

    Ich kenne deine Scripte nicht und kann dir deshalb keine Erklärung geben. Wenn du trotz meiner einleitenden Worte an der Weiterleitung festhalten willst, könntest du zum Testen mal ein paar kleine Verzögerungen mit sleep() (2, 3 Sekunden werden reichen) einbauen, bevor du die Session öffnest, und nachdem du den Schreibzugriff beendet hast. Vielleicht läuft irgendetwas zu schnell ab.
    Du könntest auch die Verzögerung so groß setzen, dass dir Zeit bleibt, den Inhalt der Sessiondaten-Datei zu inspizieren, so dass du möglicherweise feststellen kannst, dass der Wert bereits vor der nächsten Anforderung des Browsers (aufgrund des Location-Headers) in der Session steht.

    Außerdem solltest du bei allem beachten, dass sich Besucher nicht immer an die von dir vorgesehene Reihenfolge des Seitenaufrufs halten. Ebenso sollten deine Seiten ihre Ihnalte auch ohne Session hergeben, denn Suchmaschinen verwenden im Allgemeinen keine Sessions, bzw. die dafür notwendigen Cookies.

    echo "$verabschiedung $name";

    1. var $begrüßung = dedlfix;

      Vielen Dank für Deine Antwort, <?=$begrüßung?> !

      Das sind zwei Fehler auf einmal. Zum einen schreibt HTTP vor, dass der Location-Header eine absolute URL (http://...) liefert und keine relative.

      Danke, das ist mir entgangen. Damit hat sich der Grund für meine Weiterleitung eigentlich auch schon erledigt.

      Zum anderen ist das vorgesehene Mittel bei Abruf einer nicht vorhandenen Ressource der Statuscode 404 und keine Weiterleitung (302) auf eine Ressource, die du vermutlich mit Statuscode 200 auslieferst.

      Das verstehe ich jetzt nicht. Wird der Statuscode 404 nicht bereits in dem Moment gesendet in dem die Originaldatei nicht gefunden wurde? Deshalb tritt die .htaccess doch erst in aktion, oder? Und wenn ich dort ein statisches Ziel (ich meine eine Datei ohne Weiterleitung) angebe bekomme ich doch auch 200 als Rückgabe?
      Irgendwie habe ich da noch einen gedanklichen Knoten.

      Guter Tipp mit der Verzögerung. Die Weiterleitung hat sich zwar erledigt aber ich möchte trotzdem wissen, an welcher Stelle meine Scripte sich verselbständigen.

      Außerdem solltest du bei allem beachten, dass sich Besucher nicht immer an die von dir vorgesehene Reihenfolge des Seitenaufrufs halten. Ebenso sollten deine Seiten ihre Ihnalte auch ohne Session hergeben, denn Suchmaschinen verwenden im Allgemeinen keine Sessions, bzw. die dafür notwendigen Cookies.

      Primär wird die Contentvariable in der URL weitergegeben ($_GET). Die Session besteht nur alternativ damit ich nicht jede URL innerhalb der Inhalte mit allen Parametern (es gibt noch mehr davon) ausstatten muß.

      Caro

      1. echo $begrüßung;

        Zum anderen ist das vorgesehene Mittel bei Abruf einer nicht vorhandenen Ressource der Statuscode 404 und keine Weiterleitung (302) auf eine Ressource, die du vermutlich mit Statuscode 200 auslieferst.
        Das verstehe ich jetzt nicht. Wird der Statuscode 404 nicht bereits in dem Moment gesendet in dem die Originaldatei nicht gefunden wurde? Deshalb tritt die .htaccess doch erst in aktion, oder?

        Der Statuscode wird zusammen mit der Antwort gesendet, und jede Antwort hat einen Statuscode. Im Fehlerfall hat die Antwort den Statuscode 404.
        Sinn der ErrorDocument-Konfiguration des Apachen ist es, eine eigene Antwort statt des vorgegebenen Textes zu senden. Wenn deine Fehlerseite nun aber mittels eines Location-Headers umleitet, wird dazu von PHP auch der Statuscode auf 302 gesetzt. Das ist ein Sonderfall der header()-Funktion.

        Und wenn ich dort ein statisches Ziel (ich meine eine Datei ohne Weiterleitung) angebe bekomme ich doch auch 200 als Rückgabe?

        Das sollte nicht so sein. Das Dokument wird zusammen mit dem Statuscode 404 vom Apachen ausgeliefert. Du kannst das beispielsweise mit der livehttpheaders-Extension des Firefox nachvollziehen.
        (Ein Sonderfall ist, wenn du das ErrorDocument als vollständige URL konfigurierst, dann gibt es eine Umleitung.)

        echo "$verabschiedung $name";

        1. Danke langsam fange ich an, die Sache mit den Statusmeldungen (ansatzweise) zu verstehen.
          Jedenfalls hast Du mich erstmal vor einer Dummheit bewahrt ...
          Caro