PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI


105

Sto costruendo un'applicazione PHP in CodeIgniter. CodeIgniter invia tutte le richieste al controllore principale: index.php. Tuttavia, non mi piace vedere index.phpnell'URI. Ad esempio, http://www.example.com/faq/whateververrà indirizzato a http://www.example.com/index.php/faq/whatever. Ho bisogno di un modo affidabile per uno script per sapere qual è il suo indirizzo, quindi saprà cosa fare con la navigazione. Ho usato mod_rewrite, come da documentazione CodeIgniter.

La regola è la seguente:

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

Normalmente, mi limito a controllare php_self, ma in questo caso è sempre index.php. Posso ottenerlo da REQUEST_URI, PATH_INFOecc., Ma sto cercando di decidere quale sarà più affidabile. Qualcuno sa (o sapere dove trovare) la vera differenza tra PHP_SELF, PATH_INFO, SCRIPT_NAME, e REQUEST_URI? Grazie per l'aiuto!

Nota : ho dovuto aggiungere spazi, poiché SO vede il carattere di sottolineatura e lo rende corsivo per qualche motivo.

Aggiornato : corretti gli spazi.

Risposte:


51

La documentazione PHP può dirti la differenza:

'PHP_SELF'

Il nome del file dello script attualmente in esecuzione, relativo alla radice del documento. Ad esempio, $ _SERVER ['PHP_SELF'] in uno script all'indirizzo http://example.com/test.php/foo.bar sarebbe /test.php/foo.bar . La costante __FILE__ contiene il percorso completo e il nome del file corrente (cioè incluso). Se PHP è in esecuzione come processore a riga di comando, questa variabile contiene il nome dello script a partire da PHP 4.3.0. In precedenza non era disponibile.

'SCRIPT_NAME'

Contiene il percorso dello script corrente. Questo è utile per le pagine che devono puntare a se stesse. La costante __FILE__ contiene il percorso completo e il nome del file corrente (cioè incluso).

'REQUEST_URI'

L'URI che è stato fornito per accedere a questa pagina; ad esempio, "/index.html" .

PATH_INFO non sembra essere documentato ...


3
Questo molto probabilmente non riguarda la documentazione PHP ma il CGI :) E lì PATH_INFO è documentato: tools.ietf.org/html/rfc3875#section-4 Ma ci sono alcuni problemi noti che Apache e nginx non danno sempre questa variabile.
SimonSimCity

1
La risposta di Odino di seguito aggiunge utili spiegazioni che sono integrate con esempi. Trovo difficile capire cosa rappresentano queste variabili in un contesto generale con un path_info, una stringa di query, alcuni reindirizzamenti, alcuni alias, su diversi sistemi operativi, da CLI vs SERVER, ecc.

3
-1 Solo come spiegazione del motivo per cui ho downvotato: l'intera ragione per cui sono arrivato a questo post è perché la documentazione non è chiara. La risposta di Odino di seguito fornisce una chiara spiegazione delle differenze tra queste variabili. Penso che sia una risposta insufficiente per copiare e incollare facilmente reperibile ma anche documentazione insufficiente. Credo che la maggior parte delle persone avrebbe già dovuto visitare la documentazione per conoscere l'elenco degli elementi nella variabile $ _SERVER menzionata sopra.
dallin

229

Alcuni esempi pratici delle differenze tra queste variabili:
Esempio 1. PHP_SELF è diverso da SCRIPT_NAME solo quando l'URL richiesto è nel formato:
http://example.com/test.php/foo/bar

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

(questo sembra essere l'unico caso in cui PATH_INFO contiene informazioni sensibili [PATH_INFO] => / foo / bar) Nota: questo era diverso in alcune versioni PHP precedenti (<= 5.0?).

Esempio 2. REQUEST_URI è diverso da SCRIPT_NAME quando viene inserita una stringa di query non vuota:
http://example.com/test.php?foo=bar

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

Esempio 3. REQUEST_URI è diverso da SCRIPT_NAME quando è attivo il reindirizzamento lato server (ad esempio mod_rewrite su apache):

http://example.com/test.php

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

Esempio 4. REQUEST_URI è diverso da SCRIPT_NAME quando si gestiscono errori HTTP con gli script.
Utilizzo della direttiva Apache ErrorDocument 404 /404error.php
http://example.com/test.php

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

Sul server IIS utilizzando pagine di errore personalizzate
http://example.com/test.php

[SCRIPT_NAME] => /404error.php
[REQUEST_URI] => /404error.php?404;http://example.com/test.php

21
+1, "Un esempio non è un modo per imparare, è l'unico modo per imparare." - Devo sempre ricontrollare questa roba, ricerca molto bella sugli errori 404. =)
Alix Axel

16
+1: la prima volta nella mia vita ho capito la differenza. Dovrebbero aggiornare la documentazione PHP con la tua risposta
Marco Demaio

Esempio1: [SCRIPT_NAME] => /test.php/ Non dovrebbe esserci alcuna "/" alla fine: Esempio1: [SCRIPT_NAME] => /test.php Comunque questo è quello che vedo in PHP 5.3.6. Bei esempi.
Dawid Ohia

Hai ragione JohnM2, ora ho controllato PHP 5.4 e il risultato per l'URL /pinfo.php/first/second?third=fourth è il seguente: QUERY_STRING => third = 4th REQUEST_URI => /pinfo.php/first/second ? terzo = quarto SCRIPT_NAME => /pinfo.php PATH_INFO => / primo / secondo
Odino

Ho provato anche questo su 5.2.17 e non c'è /alla fine del file SCRIPT_NAME. Questo sembra essere coerente in PHP 5.2-5.4 quindi, considerando la modifica della risposta per riflettere questo.
Fabrício Matté

24

PATH_INFO è disponibile solo quando si utilizza htaccess in questo modo:

Esempio 1

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

Rimane lo stesso

[SCRIPT_NAME] => /index.php

Radice

http://domain.com/

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

Sentiero

http://domain.com/test

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

Stringa della domanda

http://domain.com/test?123

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

Esempio 2

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

Rimane lo stesso

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

Radice

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Sentiero

http://domain.com/test

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

Stringa della domanda

http://domain.com/test?123

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

Esempio 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]

o

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]

Rimane lo stesso

[SCRIPT_NAME] => /index.php

Radice

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

Sentiero

http://domain.com/test

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

linguaggio

http://domain.com/en

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

Percorso linguistico

http://domain.com/en/test

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

Stringa di query della lingua

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

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

È stato fantastico. Grazie per l'aiuto!
Gabriel Fair

1
Questa risposta è scritta in un modo che suggerisce che solo la riscrittura dell'URL può creare un path_info, ma, ovviamente, le informazioni sul percorso possono essere inserite direttamente nell'URL originale.

12

Percorsi PHP

    $_SERVER['REQUEST_URI']    = Percorso Web, URI richiesto
    $_SERVER['PHP_SELF']    = Percorso Web, file richiesto + informazioni
    $_SERVER['SCRIPT_NAME']    sul percorso = Percorso Web, file richiesto
    $_SERVER['SCRIPT_FILENAME']   = Percorso file, file richiesto
    __FILE__    = Percorso file, file corrente

Dove

  • Il percorso del file è un percorso del file di sistema simile /var/www/index.php, dopo la risoluzione dell'alias
  • Il percorso Web è un percorso del documento del server simile a /index.phpfrom http://foo.com/index.phpe potrebbe non corrispondere nemmeno a nessun file
  • File corrente indica il file di script incluso , non qualsiasi script che lo include
  • File richiesto indica il file di script includer, non quello incluso
  • L'URI è la richiesta HTTP come /index.php?foo=bar, prima di qualsiasi riscrittura dell'URL
  • Le informazioni sul percorso sono tutti i dati Apache aggiuntivi che si trovano dopo il nome dello script ma prima della stringa di query

Ordine di operazione

  1. Il client invia al server una richiesta HTTP REQUEST_URI
  2. Il server esegue qualsiasi riscrittura URL da file .htaccess, ecc. Per ottenerePHP_SELF
  3. Il server si separa PHP_SELFin SCRIPT_FILENAME+PATH_INFO
  4. Il server esegue la risoluzione degli alias e converte l'intero percorso dell'URL in un percorso del file di sistema da ottenereSCRIPT_FILENAME
  5. Il file di script risultante può includerne altri, dove si __FILE__riferisce al percorso del file corrente

Questo è buono. Ecco i miei commenti. Innanzitutto, sia $ _SERVER ['SCRIPT_NAME'] e $ _SERVER ['SCRIPT_FILENAME'] sono nomi di script, tranne per il fatto che l'ultimo è dopo l'esecuzione degli alias. Secondo, $ _SERVER ['PHP_SELF'] non è lo script, ma lo script + le informazioni sul percorso. Ancora una volta, $ _SERVER ["SCRIPT_NAME"] è lo script (prima degli alias). Infine, è utile sapere in quale fase, dopo o prima delle regole di riscrittura, dopo o prima degli alias, queste variabili vengono definite. Vedi la mia risposta.

@ Dominic108 Ho rivisto la mia risposta in base ai tuoi suggerimenti, ho riordinato un po 'le cose e ho aggiunto una sezione Ordine di operazione. Fatemi sapere cosa ne pensate. Grazie!
Beejor

Nel tuo ordine, devi scambiare $_SERVER['SCRIPT_NAME']e   $_SERVER['PHP_SELF'], poiché mod_rewrite crea l'intero percorso, che è $_SERVER['PHP_SELF']. La separazione avviene dopo. Notare che gli alias considerano anche l'intero percorso per definire il nome del file dello script, ma la separazione che ha definito script_name e path_info è già avvenuta, quindi non saranno influenzati.

@ Dominic108 Ho rivisto di nuovo la mia risposta. Per qualche motivo la tua proposta di modifica è stata rifiutata, anche se per quanto ne so, hai ragione sul fatto che due dei miei articoli erano fuori uso. Non conosco gli alias, quindi mi affido alla tua esperienza per quella parte. Grazie ancora!
Beejor

5

Potresti voler esaminare la classe URI e utilizzare $ this-> uri-> uri_string ()

Restituisce una stringa con l'URI completo.

Ad esempio, se questo è il tuo URL completo:

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

La funzione restituirà questo:

/news/local/345

Oppure puoi utilizzare i segmenti per eseguire il drill-down di aree specifiche senza dover elaborare valori di analisi / regex


Grazie - questa è una buona idea, ma li sto usando in un hook pre-sistema che dovrà essere eseguito prima che il controller sia attivo e funzionante.
Eli

4

Personalmente uso il $REQUEST_URIcome fa riferimento all'URI inserito e non alla posizione sul disco del server.


È sempre l'URI completo?
Eli

In genere, è possibile riscontrare problemi con Apache su Windows, ma è solo per gli URI che non si risolvono.
Xenph Yan

4

C'è molto poco da aggiungere alla risposta di Odino. Ho appena sentito di fornire un esempio completo dalla richiesta HTTP al file effettivo sul file system per illustrare gli effetti della riscrittura e degli alias degli URL. Sul file system lo script /var/www/test/php/script.phpè

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

dove /var/www/test/php/script_included.phpè

<?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>";  
?>

ed /var/www/test/.htaccess è

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

e il file di configurazione di Apache include l'alias

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

e la richiesta http è

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

L'output sarà

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

Quanto segue è sempre valido

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

Se non sono presenti mod_rewrite, mod_dir, ErrorDocument rewrite o qualsiasi forma di riscrittura URL, abbiamo anche

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

Gli alias influenzano i percorsi dei file di sistema SCRIPT_FILENAMEe __FILE__non i percorsi URL, che sono stati definiti in precedenza - vedere le eccezioni di seguito. Gli alias potrebbero utilizzare l'intero percorso dell'URL, inclusi PATH_INFO. Non potrebbe esserci alcuna connessione tra SCRIPT_NAMEe SCRIPT_FILENAME.

Non è del tutto esatto che gli alias non vengano risolti nel momento in cui [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] viene definito il percorso dell'URL , perché gli alias sono considerati per la ricerca nel file system e sappiamo dall'esempio 4 nella risposta di Odin che il file system viene cercato per determinare se il file esiste, ma questo è rilevante solo quando il file non viene trovato. Allo stesso modo, mod_dir chiama mod_alias per cercare nel file system, ma questo è rilevante solo se hai un alias come Alias \index.php \var\www\index.phpe la richiesta uri è una directory.


Ciao Dominic108, grazie per la revisione. Penso che sia utile includere le informazioni di riscrittura. Per me era implicito, ma per altri potrebbe non essere così intuitivo.
Beejor

1

Se dimentichi quali variabili fanno cosa, puoi scrivere un piccolo script che usa phpinfo () e chiamarlo da un URL con una stringa di query. Poiché le installazioni del software server presentano le variabili restituite da PHP, è sempre una buona idea controllare l'output della macchina nel caso in cui le riscritture nel file di configurazione del server stiano causando risultati diversi dal previsto. Salvalo come qualcosa come _inf0.php:

<?php
    $my_ip = '0.0.0.0';

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

Allora chiameresti /_inf0.php?q=500


-1

Esegui il backup un secondo, hai adottato l'approccio sbagliato per cominciare. Perché non farlo e basta

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

anziché? Quindi afferralo con$_GET['url'];


Perché reinventare la ruota? Questi dati sono molto più facilmente accessibili!
Kenneth

E vi è ulteriore complessità se si prevede che la richiesta originale abbia una stringa di query. Nel suo stato corrente, il codice sopra sovrascriverà semplicemente la stringa di query. Se si uniscono stringhe di query ( QSAflag), i parametri della stringa di query possono essere potenzialmente sovrascritti (ad esempio, se era necessario un urlparametro nella richiesta iniziale) o, peggio, essere vulnerabili agli attacchi XSS.
MrWhite
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.