PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

105

Ich erstelle eine PHP-Anwendung in CodeIgniter. CodeIgniter sendet alle Anforderungen an den Hauptcontroller : index.php. Ich mag es jedoch nicht, index.phpin der URI zu sehen. Zum Beispiel http://www.example.com/faq/whateverwird zu routen http://www.example.com/index.php/faq/whatever. Ich brauche eine zuverlässige Methode, damit ein Skript weiß, wie seine Adresse lautet, damit es weiß, was mit der Navigation zu tun ist. Ich habe mod_rewritegemäß CodeIgniter-Dokumentation verwendet.

Die Regel lautet wie folgt:

RewriteEngine on
RewriteCond $1 !^(images|inc|favicon\.ico|index\.php|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L] 

Normalerweise würde ich nur nachsehen php_self, aber in diesem Fall ist es immer so index.php. Ich kann es von bekommen REQUEST_URI, PATH_INFOetc., aber ich versuche zu entscheiden , welche die zuverlässigste sein wird. Hat jemand wissen (oder wissen , wo zu finden) , um den Unterschied zwischen PHP_SELF, PATH_INFO, SCRIPT_NAMEund REQUEST_URI? Danke für Ihre Hilfe!

Hinweis : Ich musste Leerzeichen hinzufügen, da SO den Unterstrich sieht und ihn aus irgendeinem Grund kursiv macht.

Aktualisiert : Die Leerzeichen wurden korrigiert.

Eli
quelle

Antworten:

51

Die PHP-Dokumentation kann Ihnen den Unterschied erklären:

'PHP_SELF'

Der Dateiname des aktuell ausgeführten Skripts relativ zum Dokumentstamm. Zum Beispiel $ _SERVER [ ‚PHP_SELF‘] in einem Skript an der Adresse http://example.com/test.php/foo.bar wäre /test.php/foo.bar . Die Konstante __FILE__ enthält den vollständigen Pfad und Dateinamen der aktuellen (dh enthaltenen) Datei. Wenn PHP als Befehlszeilenprozessor ausgeführt wird, enthält diese Variable den Skriptnamen seit PHP 4.3.0. Bisher war es nicht verfügbar.

'SCRIPT_NAME'

Enthält den Pfad des aktuellen Skripts. Dies ist nützlich für Seiten, die auf sich selbst verweisen müssen. Die Konstante __FILE__ enthält den vollständigen Pfad und Dateinamen der aktuellen (dh enthaltenen) Datei.

'REQUEST_URI'

Die URI, die angegeben wurde, um auf diese Seite zuzugreifen; Zum Beispiel '/index.html' .

PATH_INFO scheint nicht dokumentiert zu sein ...

Jeremy Ruten
quelle
3
Hier geht es höchstwahrscheinlich nicht um die PHP-Dokumentation, sondern um das CGI :) Und dort ist PATH_INFO dokumentiert: tools.ietf.org/html/rfc3875#section-4 Es gibt jedoch einige bekannte Probleme, bei denen Apache und Nginx diese Variable nicht immer angeben .
SimonSimCity
1
Odins Antwort unten fügt nützliche Erklärungen hinzu, die durch Beispiele ergänzt werden. Es fällt mir schwer zu verstehen, was diese Variablen in einem allgemeinen Kontext mit einer path_info, einer Abfragezeichenfolge, einer Umleitung, einigen Aliasen auf verschiedenen Betriebssystemen von CLI gegen SERVER usw. darstellen.
3
-1 Nur als Erklärung, warum ich abgelehnt habe: Der ganze Grund, warum ich zu diesem Beitrag gekommen bin, ist, dass die Dokumentation nicht klar ist. Die folgende Antwort von Odin liefert eine klare Erklärung der Unterschiede zwischen diesen Variablen. Ich denke, es ist eine unzureichende Antwort, nur leicht zu findende, aber auch unzureichende Dokumentation zu kopieren und einzufügen. Ich glaube, die meisten Leute hätten bereits die Dokumentation besuchen müssen, um überhaupt etwas über die Liste der Elemente in der oben erwähnten Variablen $ _SERVER zu erfahren.
Dallas
229

Einige praktische Beispiele für die Unterschiede zwischen diesen Variablen:
Beispiel 1. PHP_SELF unterscheidet sich von SCRIPT_NAME nur, wenn die angeforderte URL in der folgenden Form vorliegt:
http://example.com/test.php/foo/bar

[PHP_SELF] => /test.php/foo/bar
[SCRIPT_NAME] => /test.php

(Dies scheint der einzige Fall zu sein, in dem PATH_INFO sinnvolle Informationen enthält [PATH_INFO] => / foo / bar) Hinweis: Dies war in einigen älteren PHP-Versionen (<= 5.0?) anders.

Beispiel 2. REQUEST_URI unterscheidet sich von SCRIPT_NAME, wenn eine nicht leere Abfragezeichenfolge eingegeben wird:
http://example.com/test.php?foo=bar

[SCRIPT_NAME] => /test.php
[REQUEST_URI] => /test.php?foo=bar

Beispiel 3. REQUEST_URI unterscheidet sich von SCRIPT_NAME, wenn die serverseitige Umleitung aktiviert ist (z. B. mod_rewrite für Apache):

http://example.com/test.php

[REQUEST_URI] => /test.php
[SCRIPT_NAME] => /test2.php

Beispiel 4. REQUEST_URI unterscheidet sich von SCRIPT_NAME, wenn HTTP-Fehler mit Skripten behandelt werden.
Verwenden der Apache-Direktive ErrorDocument 404 /404error.php
http://example.com/test.php

[REQUEST_URI] => /test.php
[SCRIPT_NAME] => /404error.php

Auf einem IIS-Server mit benutzerdefinierten Fehlerseiten
http://example.com/test.php

[SCRIPT_NAME] => /404error.php
[REQUEST_URI] => /404error.php?404;http://example.com/test.php
Odin
quelle
21
+1, "Ein Beispiel ist kein Weg zu lernen, es ist der einzige Weg zu lernen." - Ich muss dieses Zeug immer noch einmal überprüfen, sehr gute Recherche zu den 404-Fehlern. =)
Alix Axel
16
+1: Zum ersten Mal in meinem Leben habe ich den Unterschied verstanden. Sie sollten die PHP-Dokumentation mit Ihrer Antwort aktualisieren
Marco Demaio
Beispiel 1: [SCRIPT_NAME] => /test.php/ Am Ende sollte kein "/" stehen: Beispiel 1: [SCRIPT_NAME] => /test.php Wie auch immer, das sehe ich in PHP 5.3.6. Schöne Beispiele.
Dawid Ohia
Sie haben Recht, JohnM2. Ich habe jetzt PHP 5.4 überprüft und das Ergebnis für die URL /pinfo.php/first/second?third=fourth lautet wie folgt: QUERY_STRING => drittes = viertes REQUEST_URI => /pinfo.php/first/second dritter = vierter SCRIPT_NAME => /pinfo.php PATH_INFO => / erster / zweiter
Odin
Ich habe dies auch am 5.2.17 getestet und es gibt keine /am Ende des SCRIPT_NAME. Dies scheint in PHP 5.2-5.4 konsistent zu sein, wenn man bedenkt, dass die Antwort bearbeitet wird, um dies widerzuspiegeln.
Fabrício Matté
24

PATH_INFO ist nur verfügbar, wenn htaccess wie folgt verwendet wird:

Beispiel 1

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

Bleibt das selbe

[SCRIPT_NAME] => /index.php

Wurzel

http://domain.com/

[PHP_SELF]     => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI]  => /
[QUERY_STRING] => 

Pfad

http://domain.com/test

[PHP_SELF]     => /index.php/test
[PATH_INFO]    => /test
[REQUEST_URI]  => /test
[QUERY_STRING] => 

Abfragezeichenfolge

http://domain.com/test?123

[PHP_SELF]     => /index.php/test
[PATH_INFO]    => /test
[REQUEST_URI]  => /test?123
[QUERY_STRING] => 123

Beispiel 2

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php?url=$1 [L,QSA]

Bleibt das selbe

[SCRIPT_NAME]  => /index.php
[PHP_SELF]     => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)

Wurzel

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Pfad

http://domain.com/test

[REQUEST_URI]  => /test
[QUERY_STRING] => url=test

Abfragezeichenfolge

http://domain.com/test?123

[REQUEST_URI]  => /test?123
[QUERY_STRING] => url=test&123

Beispiel 3

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(([a-z]{2})|(([a-z]{2})/)?(.*))$ index.php/$5 [NC,L,E=LANGUAGE:$2$4]

oder

RewriteRule ^([a-z]{2})(/(.*))?$ $3 [NC,L,E=LANGUAGE:$1]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(favicon\.ico|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

Bleibt das selbe

[SCRIPT_NAME] => /index.php

Wurzel

http://domain.com/

[PHP_SELF]          => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI]       => /
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] IS NOT AVAILABLE

Pfad

http://domain.com/test

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /test
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] => 

Sprache

http://domain.com/de

[PHP_SELF]          => /index.php/
[PATH_INFO]         => /
[REQUEST_URI]       => /en
[QUERY_STRING]      => 
[REDIRECT_LANGUAGE] => en

Sprachpfad

http://domain.com/de/test

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /en/test
[REDIRECT_LANGUAGE] => en

Sprachabfragezeichenfolge

http://domain.com/de/test?123

[PHP_SELF]          => /index.php/test
[PATH_INFO]         => /test
[REQUEST_URI]       => /en/test?123
[QUERY_STRING]      => 123
[REDIRECT_LANGUAGE] => en
Mike
quelle
Das war großartig. Danke für Ihre Hilfe!
Gabriel Fair
1
Diese Antwort ist so geschrieben, dass nur das Umschreiben von URLs eine path_info erstellen kann, aber natürlich können die Pfadinformationen direkt in die ursprüngliche URL eingegeben werden.
11

PHP-Pfade

    $_SERVER['REQUEST_URI']    = Webpfad, angeforderter URI
    $_SERVER['PHP_SELF']    = Webpfad, angeforderte Datei + Pfadinfo
    $_SERVER['SCRIPT_NAME']    = Webpfad, angeforderte Datei
    $_SERVER['SCRIPT_FILENAME']   = Dateipfad, angeforderte Datei
    __FILE__    = Dateipfad, aktuelle Datei

Wo

  • Der Dateipfad ist ein Systemdateipfad wie /var/www/index.phpnach der Aliasauflösung
  • Der Webpfad ist ein Serverdokumentpfad wie /index.phpvon http://foo.com/index.php und entspricht möglicherweise nicht einmal einer Datei
  • Aktuelle Datei bedeutet die enthaltene Skriptdatei , kein Skript, das sie enthält
  • Angeforderte Datei bedeutet das Inklusionsskriptdatei , nicht die enthaltene
  • URI ist die HTTP-Anfrage wie/index.php?foo=bar vor dem Umschreiben einer URL
  • Pfadinformationen sind alle zusätzlichen Apache-Daten, die sich nach dem Skriptnamen, aber vor der Abfragezeichenfolge befinden

Reihenfolge der Bedienung

  1. Der Client sendet dem Server eine HTTP-Anfrage REQUEST_URI
  2. Der Server führt ein Umschreiben der URL durch aus .htaccess-Dateien usw. durch, um sie abzurufenPHP_SELF
  3. Server trennt sich PHP_SELFinSCRIPT_FILENAME +PATH_INFO
  4. Der Server führt eine Aliasauflösung durch und konvertiert den gesamten URL-Pfad in einen Systemdateipfad um ihn abzurufenSCRIPT_FILENAME
  5. Die resultierende Skriptdatei kann andere enthalten, wobei __FILE__auf den Pfad zur aktuellen Datei verwiesen wird
Beejor
quelle
Das ist gut. Hier sind meine Kommentare. Erstens sind sowohl $ _SERVER ['SCRIPT_NAME'] als auch $ _SERVER ['SCRIPT_FILENAME'] Skriptnamen, mit der Ausnahme, dass letzterer nach der Ausführung von Aliasen ausgeführt wird. Zweitens ist $ _SERVER ['PHP_SELF'] nicht das Skript, sondern das Skript + die Pfadinformationen. Wieder ist $ _SERVER ['SCRIPT_NAME'] das Skript (vor Aliasnamen). Schließlich ist es hilfreich zu wissen, zu welchem ​​Zeitpunkt nach oder vor dem Umschreiben von Regeln, nach oder vor Aliasen diese Variablen definiert werden. Siehe meine Antwort.
@ Dominic108 Ich habe meine Antwort basierend auf Ihren Vorschlägen überarbeitet, die Dinge ein wenig aufgeräumt und einen Abschnitt zur Reihenfolge der Operationen hinzugefügt. Lass mich wissen was du denkst. Vielen Dank!
Beejor
In Ihrer Bestellung müssen Sie tauschen $_SERVER['SCRIPT_NAME']und   $_SERVER['PHP_SELF'], da mod_rewrite den gesamten Pfad erstellen, das heißt $_SERVER['PHP_SELF']. Die Trennung erfolgt als nächstes. Beachten Sie, dass Aliase auch den gesamten Pfad zum Definieren des Skriptdateinamens berücksichtigen, die Trennung von Skriptname und Pfadinfo jedoch bereits erfolgt ist, sodass sie nicht betroffen sind.
@ Dominic108 Ich habe meine Antwort erneut überarbeitet. Aus irgendeinem Grund wurde Ihr Bearbeitungsvorschlag abgelehnt, obwohl Sie meines Wissens zu Recht feststellen, dass zwei meiner Artikel nicht in Ordnung waren. Ich bin mit Aliasnamen nicht so vertraut, daher verlasse ich mich in diesem Teil auf Ihr Fachwissen. Danke noch einmal!
Beejor
5

Möglicherweise möchten Sie einen Blick in die URI-Klasse werfen und $ this-> uri-> uri_string () verwenden

Gibt eine Zeichenfolge mit dem vollständigen URI zurück.

Wenn dies beispielsweise Ihre vollständige URL ist:

http://example.com/index.php/news/local/345

Die Funktion würde dies zurückgeben:

/news/local/345

Sie können die Segmente auch verwenden, um einen Drilldown für bestimmte Bereiche durchzuführen, ohne Parsing- / Regex-Werte erstellen zu müssen

Adam
quelle
Vielen Dank - dies ist eine gute Idee, aber ich verwende diese in einem Pre-System-Hook, der ausgeführt werden muss, bevor der Controller betriebsbereit ist.
Eli
4

Persönlich verwende ich das, $REQUEST_URIda es auf den eingegebenen URI verweist und nicht auf den Speicherort auf der Server-CD.

Xenph Yan
quelle
Ist es immer die vollständige URI?
Eli
In der Regel können unter Windows Probleme mit Apache auftreten, die jedoch nur für URIs nicht behoben werden können.
Xenph Yan
4

Zu Odins Antwort gibt es sehr wenig hinzuzufügen. Ich wollte nur ein vollständiges Beispiel von der HTTP-Anforderung für die eigentliche Datei im Dateisystem bereitstellen, um die Auswirkungen des Umschreibens von URLs und Aliasnamen zu veranschaulichen. Das Skript auf dem Dateisystem /var/www/test/php/script.phpist

<?php
include ("script_included.php")
?>

wo /var/www/test/php/script_included.phpist

<?php
echo "REQUEST_URI: " .  $_SERVER['REQUEST_URI'] . "<br>"; 
echo "PHP_SELF: " .  $_SERVER['PHP_SELF'] . "<br>";
echo "QUERY_STRING: " .  $_SERVER['QUERY_STRING'] . "<br>";
echo "SCRIPT_NAME: " .  $_SERVER['SCRIPT_NAME'] . "<br>";
echo "PATH_INFO: " .  $_SERVER['PATH_INFO'] . "<br>";
echo "SCRIPT_FILENAME: " . $_SERVER['SCRIPT_FILENAME'] . "<br>";
echo "__FILE__ : " . __FILE__ . "<br>";  
?>

und /var/www/test/.htaccess ist

RewriteEngine On
RewriteRule before_rewrite/script.php/path/(.*) after_rewrite/script.php/path/$1 

und die Apache-Konfigurationsdatei enthält den Alias

Alias /test/after_rewrite/ /var/www/test/php/

und die http Anfrage ist

www.example.com/test/before_rewrite/script.php/path/info?q=helloword

Die Ausgabe wird sein

REQUEST_URI: /test/before_rewrite/script.php/path/info?q=helloword
PHP_SELF: /test/after_rewrite/script.php/path/info
QUERY_STRING: q=helloword
SCRIPT_NAME: /test/after_rewrite/script.php
PATH_INFO: /path/info
SCRIPT_FILENAME: /var/www/test/php/script.php
__FILE__ : /var/www/test/php/script_included.php

Folgendes gilt immer

PHP_SELF = SCRIPT_NAME + PATH_INFO = full url path between domain and query string. 

Wenn es kein Umschreiben von mod_rewrite, mod_dir, ErrorDocument oder irgendeine Form des Umschreibens von URLs gibt, haben wir auch

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

Die Aliase wirken sich auf die Systemdateipfade SCRIPT_FILENAMEund __FILE__nicht auf die zuvor definierten URL-Pfade aus - siehe Ausnahmen unten. Aliase verwenden möglicherweise den gesamten URL-Pfad, einschließlich PATH_INFO. Es konnte überhaupt keine Verbindung zwischen SCRIPT_NAMEund geben SCRIPT_FILENAME.

Es ist nicht ganz genau, dass Aliase zum Zeitpunkt der [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] Definition des URL-Pfads nicht aufgelöst werden , da Aliase für die Suche im Dateisystem in Betracht gezogen werden und wir aus Beispiel 4 in Odins Antwort wissen, dass das Dateisystem durchsucht wird, um festzustellen, ob die Datei vorhanden ist. Dies ist jedoch nur relevant, wenn die Datei nicht gefunden wird. In ähnlicher Weise ruft mod_dir mod_alias auf, um das Dateisystem zu durchsuchen. Dies ist jedoch nur relevant, wenn Sie einen Alias ​​wie haben Alias \index.php \var\www\index.phpund die Anforderungs-URL ein Verzeichnis ist.


quelle
Hallo Dominic108, danke für die Überarbeitung. Ich denke, es ist nützlich, die Umschreibungsinformationen einzuschließen. Für mich war es impliziert, aber für andere mag es nicht so intuitiv sein.
Beejor
1

Wenn Sie jemals vergessen, welche Variablen was tun, können Sie ein kleines Skript schreiben, das verwendet phpinfo () verwendet, und es von einer URL mit einer Abfragezeichenfolge aufrufen. Da Serversoftwareinstallationen die von PHP zurückgegebenen Variablen enthalten, ist es immer eine gute Idee, die Ausgabe des Computers zu überprüfen, falls das Umschreiben in der Serverkonfigurationsdatei zu anderen Ergebnissen führt als erwartet. Speichern Sie es als etwas wie _inf0.php:

<?php
    $my_ip = '0.0.0.0';

   if($_SERVER['REMOTE_ADDR']==$my_ip){
     phpinfo();
   } else {
     //something
   }

Dann würden Sie anrufen /_inf0.php?q=500

Absoluter Nullpunkt
quelle
-1

Sichern Sie eine Sekunde, Sie haben zunächst den falschen Ansatz gewählt. Warum nicht einfach so machen?

RewriteEngine on
RewriteCond $1 !^(images|inc|favicon\.ico|index\.php|robots\.txt)
RewriteRule ^(.*)$ /index.php?url=$1 [L]

stattdessen? Dann schnapp es dir mit$_GET['url'];

Kate Gregory
quelle
Warum das Rad neu erfinden? Diese Daten sind viel einfacher zugänglich!
Kenneth
Und es gibt zusätzliche Komplexität, wenn erwartet wird, dass die ursprüngliche Anforderung eine Abfragezeichenfolge enthält. In seinem aktuellen Zustand überschreibt der obige Code einfach die Abfragezeichenfolge. Wenn Sie QSAAbfragezeichenfolgen ( Flag) zusammenführen, können Abfragezeichenfolgenparameter möglicherweise überschrieben werden (z. B. wenn Sie urlbei der ersten Anforderung einen Parameter benötigt haben ) oder, schlimmer noch, anfällig für XSS-Angriffe sein.
MrWhite