PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

105

Saya sedang membangun aplikasi PHP di CodeIgniter. CodeIgniter mengirimkan semua permintaan untuk pengendali utama: index.php. Namun, saya tidak suka melihat index.phpdi URI. Misalnya, http://www.example.com/faq/whateverakan merutekan ke http://www.example.com/index.php/faq/whatever. Saya membutuhkan cara yang andal agar skrip mengetahui alamatnya, sehingga ia akan tahu apa yang harus dilakukan dengan navigasi. Saya telah menggunakan mod_rewrite, sesuai dokumentasi CodeIgniter.

Aturannya adalah sebagai berikut:

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

Biasanya, saya hanya akan memeriksa php_self, tetapi dalam kasus ini selalu index.php. Saya bisa mendapatkannya dari REQUEST_URI,, PATH_INFOdll., Tetapi saya mencoba memutuskan mana yang paling dapat diandalkan. Apakah ada yang tahu (atau tahu di mana untuk menemukan) perbedaan nyata antara PHP_SELF, PATH_INFO, SCRIPT_NAME, dan REQUEST_URI? Terima kasih atas bantuan Anda!

Catatan : Saya harus menambahkan spasi, karena SO melihat garis bawah, dan membuatnya miring karena beberapa alasan.

Diperbarui : Memperbaiki spasi.

Eli
sumber

Jawaban:

51

The dokumentasi PHP dapat memberitahu Anda perbedaan:

'PHP_SELF'

Nama file dari skrip yang saat ini dijalankan, relatif terhadap root dokumen. Misalnya, $ _SERVER ['PHP_SELF'] dalam skrip di alamat http://example.com/test.php/foo.bar akan menjadi /test.php/foo.bar . The __FILE__ konstan berisi path lengkap dan nama file dari saat ini (termasuk yaitu) berkas. Jika PHP dijalankan sebagai pemroses baris perintah, variabel ini berisi nama skrip sejak PHP 4.3.0. Sebelumnya tidak tersedia.

'SCRIPT_NAME'

Berisi jalur skrip saat ini. Ini berguna untuk halaman yang harus mengarah ke halaman itu sendiri. The __FILE__ konstan berisi path lengkap dan nama file dari saat ini (termasuk yaitu) berkas.

'REQUEST_URI'

URI yang diberikan untuk mengakses halaman ini; misalnya, '/index.html' .

PATH_INFO sepertinya tidak didokumentasikan ...

Jeremy Ruten
sumber
3
Ini kemungkinan besar bukan tentang dokumentasi PHP tetapi CGI :) Dan ada PATH_INFO yang didokumentasikan: tools.ietf.org/html/rfc3875#section-4 Tetapi ada beberapa masalah yang diketahui bahwa Apache dan nginx tidak selalu memberikan variabel ini.
SimonSimCity
1
Jawaban Odin di bawah ini menambahkan penjelasan berguna yang dilengkapi dengan contoh. Saya merasa sulit untuk memahami apa yang diwakili oleh variabel-variabel ini dalam konteks umum dengan path_info, string kueri, beberapa pengalihan, beberapa alias, pada sistem operasi yang berbeda, dari CLI vs SERVER, dll.
3
-1 Hanya sebagai penjelasan mengapa saya menurunkan suara: seluruh alasan saya datang ke posting ini adalah karena dokumentasinya tidak jelas. Jawaban Odin di bawah ini memberikan penjelasan yang jelas tentang perbedaan antara variabel-variabel tersebut. Saya merasa ini adalah jawaban yang tidak cukup hanya dengan menyalin dan menempel dengan mudah ditemukan namun juga dokumentasi yang tidak memadai. Saya yakin kebanyakan orang pasti sudah mengunjungi dokumentasi untuk mengetahui tentang daftar elemen dalam variabel $ _SERVER yang disebutkan di atas.
dallin
229

Beberapa contoh praktis dari perbedaan antara variabel-variabel ini:
Contoh 1. PHP_SELF berbeda dari SCRIPT_NAME hanya jika URL yang diminta dalam bentuk:
http://example.com/test.php/foo/bar

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

(ini tampaknya menjadi satu-satunya kasus ketika PATH_INFO berisi informasi yang masuk akal [PATH_INFO] => / foo / bar) Catatan: ini dulunya berbeda di beberapa versi PHP yang lebih lama (<= 5.0?).

Contoh 2. REQUEST_URI berbeda dari SCRIPT_NAME ketika string kueri yang tidak kosong dimasukkan:
http://example.com/test.php?foo=bar

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

Contoh 3. REQUEST_URI berbeda dari SCRIPT_NAME saat pengalihan sisi server aktif (misalnya mod_rewrite di apache):

http://example.com/test.php

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

Contoh 4. REQUEST_URI berbeda dari SCRIPT_NAME saat menangani kesalahan HTTP dengan skrip.
Menggunakan direktif apache ErrorDocument 404 /404error.php
http://example.com/test.php

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

Di server IIS menggunakan halaman kesalahan khusus
http://example.com/test.php

[SCRIPT_NAME] => /404error.php
[REQUEST_URI] => /404error.php?404;http://example.com/test.php
Odin
sumber
21
+1, "Contoh bukanlah cara untuk belajar, itu satu-satunya cara untuk belajar." - Saya selalu harus memeriksa ulang hal ini, penelitian yang sangat bagus tentang kesalahan 404. =)
Alix Axel
16
+1: Pertama kali dalam hidup saya, saya mengerti perbedaannya. Mereka harus memperbarui dokumentasi PHP dengan jawaban Anda
Marco Demaio
Example1: [SCRIPT_NAME] => /test.php/ Seharusnya tidak ada "/" di akhir: Example1: [SCRIPT_NAME] => /test.php Bagaimanapun itu yang saya lihat di PHP 5.3.6. Contoh yang bagus.
Dawid Ohia
Anda benar JohnM2, saya sekarang telah memeriksa PHP 5.4 dan hasil untuk URL /pinfo.php/first/second?third=fourth adalah sebagai berikut: QUERY_STRING => ketiga = keempat REQUEST_URI => /pinfo.php/first/second ? ketiga = keempat SCRIPT_NAME => /pinfo.php PATH_INFO => / pertama / detik
Odin
Saya telah menguji ini pada 5.2.17 juga dan tidak ada /di akhir SCRIPT_NAME. Ini tampaknya konsisten di PHP 5.2-5.4, mempertimbangkan mengedit jawaban untuk mencerminkan itu.
Fabrício Matté
24

PATH_INFO hanya tersedia jika menggunakan htaccess seperti ini:

Contoh 1

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

Tetap sama

[SCRIPT_NAME] => /index.php

Akar

http://domain.com/

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

Jalan

http://domain.com/test

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

String Kueri

http://domain.com/test?123

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

Contoh 2

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

Tetap sama

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

Akar

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Jalan

http://domain.com/test

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

String Kueri

http://domain.com/test?123

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

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

atau

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]

Tetap sama

[SCRIPT_NAME] => /index.php

Akar

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

Jalan

http://domain.com/test

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

Bahasa

http://domain.com/en

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

Jalur bahasa

http://domain.com/en/test

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

Bahasa Query string

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
Mike
sumber
Ini bagus. Terima kasih atas bantuan Anda!
Gabriel Fair
1
Jawaban ini ditulis dengan cara yang menunjukkan bahwa hanya penulisan ulang url yang dapat membuat path_info, tetapi, tentu saja, info jalur dapat dimasukkan langsung ke URL asli.
12

Jalur PHP

    $_SERVER['REQUEST_URI']    = Jalur web, URI yang diminta
    $_SERVER['PHP_SELF']    = Jalur web, file yang diminta + jalur info
    $_SERVER['SCRIPT_NAME']    = Jalur web, file yang diminta
    $_SERVER['SCRIPT_FILENAME']   = Jalur file, file yang diminta
    __FILE__    = Jalur file, file saat ini

Dimana

  • Jalur file adalah jalur file sistem seperti /var/www/index.php, setelah resolusi alias
  • Jalur web adalah jalur dokumen server seperti /index.phpdari http://foo.com/index.php, dan bahkan mungkin tidak cocok dengan file apa pun
  • File saat ini berarti file skrip yang disertakan , bukan skrip apa pun yang menyertakannya
  • File yang diminta berarti file skrip include , bukan yang disertakan
  • URI adalah permintaan HTTP seperti /index.php?foo=bar, sebelum URL ditulis ulang
  • Info jalur adalah data Apache tambahan apa pun yang terletak setelah nama skrip tetapi sebelum string kueri

Urutan Operasi

  1. Klien mengirimkan permintaan HTTP ke server REQUEST_URI
  2. Server melakukan penulisan ulang URL dari file .htaccess, dll. Untuk mendapatkanPHP_SELF
  3. Server dipisahkan PHP_SELFmenjadi SCRIPT_FILENAME+PATH_INFO
  4. Server melakukan resolusi alias dan mengubah seluruh jalur url menjadi jalur file sistem untuk mendapatkannyaSCRIPT_FILENAME
  5. File skrip yang dihasilkan dapat menyertakan file lain, di mana __FILE__merujuk ke jalur ke file saat ini
Beejor
sumber
Ini bagus. Ini komentar saya. Pertama, $ _SERVER ['SCRIPT_NAME'] dan $ _SERVER ['SCRIPT_FILENAME'] adalah nama skrip, kecuali yang kemudian adalah setelah alias dijalankan. Kedua, $ _SERVER ['PHP_SELF'] bukanlah skrip, tetapi skrip + info jalur. Sekali lagi, $ _SERVER ['SCRIPT_NAME'] adalah skrip (sebelum alias). Terakhir, penting untuk mengetahui pada tahap apa, setelah atau sebelum aturan penulisan ulang, setelah atau sebelum alias, variabel-variabel ini didefinisikan. Lihat jawaban saya.
@ Dominic108 Saya merevisi jawaban saya berdasarkan saran Anda, merapikan sedikit, dan menambahkan bagian Order of Operation. Biarkan aku tahu apa yang kamu pikirkan. Terima kasih!
Beejor
Dalam pesanan Anda, Anda harus menukar $_SERVER['SCRIPT_NAME']dan   $_SERVER['PHP_SELF'], karena mod_rewrite membuat seluruh jalur, yaitu $_SERVER['PHP_SELF']. Pemisahan terjadi selanjutnya. Perhatikan bahwa alias juga mempertimbangkan seluruh jalur untuk menentukan nama file skrip, tetapi pemisahan yang mendefinisikan nama_krip dan path_info sudah terjadi, sehingga tidak akan terpengaruh.
@ Dominic108 Saya merevisi jawaban saya lagi. Untuk beberapa alasan proposal edit Anda ditolak, meskipun sejauh yang saya tahu, Anda benar bahwa dua item saya rusak. Saya tidak begitu paham dengan alias, jadi saya mengandalkan keahlian Anda untuk bagian itu. Terima kasih lagi!
Beejor
5

Anda mungkin ingin melihat Kelas URI dan menggunakan $ this-> uri-> uri_string ()

Mengembalikan string dengan URI lengkap.

Misalnya, jika ini adalah URL lengkap Anda:

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

Fungsi tersebut akan mengembalikan ini:

/news/local/345

Atau Anda dapat menggunakan segmen untuk menelusuri area tertentu tanpa harus menghasilkan nilai parsing / regex

Adam
sumber
Terima kasih - ini adalah ide yang bagus, tetapi saya menggunakan ini di hook pra-sistem yang perlu dijalankan sebelum pengontrol aktif dan berjalan.
Eli
4

Secara pribadi saya menggunakan $REQUEST_URIreferensi URI yang dimasukkan dan bukan lokasi di disk server.

Xenph Yan
sumber
Apakah selalu URI lengkap?
Eli
Biasanya, Anda dapat mengalami masalah dengan apache di windows, tetapi hanya untuk URI yang tidak terselesaikan.
Xenph Yan
4

Sangat sedikit yang bisa ditambahkan pada jawaban Odin. Saya hanya merasa memberikan contoh lengkap dari permintaan HTTP ke file aktual pada sistem file untuk menggambarkan efek penulisan ulang dan alias URL. Di sistem file, skripnya /var/www/test/php/script.phpadalah

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

di mana /var/www/test/php/script_included.phpadalah

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

dan /var/www/test/.htaccess adalah

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

dan file konfigurasi Apache menyertakan alias

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

dan permintaan http adalah

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

Outputnya adalah

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

Yang berikut selalu berlaku

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

Jika tidak ada mod_rewrite, mod_dir, ErrorDocument rewrite atau bentuk penulisan ulang URL apa pun, kami juga memiliki

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

Alias ​​tersebut mempengaruhi jalur file sistem SCRIPT_FILENAMEdan__FILE__ , bukan jalur URL, yang ditentukan sebelumnya - lihat pengecualian di bawah. Alias ​​mungkin menggunakan seluruh jalur URL, termasuk PATH_INFO. Tidak ada hubungan sama sekali antara SCRIPT_NAMEdan SCRIPT_FILENAME.

Tidak sepenuhnya persis bahwa alias tidak diselesaikan pada saat jalur URL [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] ditentukan, karena alias dianggap mencari sistem file dan kita tahu dari contoh 4 dalam jawaban Odin bahwa sistem file dicari untuk menentukan apakah file tersebut ada, tetapi ini hanya relevan jika file tidak ditemukan. Demikian pula, mod_dir memanggil mod_alias untuk mencari sistem file, tetapi ini hanya relevan jika Anda memiliki alias seperti Alias \index.php \var\www\index.phpdan permintaan uri adalah direktori.


sumber
Hai Dominic108, terima kasih atas revisinya. Saya pikir itu berguna untuk menyertakan info penulisan ulang. Bagi saya itu tersirat, tetapi bagi orang lain mungkin tidak begitu intuitif.
Beejor
1

Jika Anda lupa variabel mana melakukan apa, Anda dapat menulis skrip kecil yang menggunakan phpinfo () dan memanggilnya dari URL dengan string kueri. Karena penginstalan perangkat lunak server menampilkan variabel yang dikembalikan PHP, sebaiknya periksa keluaran mesin jika penulisan ulang pada file konfigurasi server menyebabkan hasil yang berbeda dari yang diharapkan. Simpan sebagai sesuatu seperti _inf0.php:

<?php
    $my_ip = '0.0.0.0';

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

Kemudian Anda akan menelepon /_inf0.php?q=500

AbsoluteƵERØ
sumber
-1

Cadangkan sebentar, Anda telah mengambil pendekatan yang salah untuk memulai. Mengapa tidak melakukan ini saja

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

sebagai gantinya? Lalu ambil dengan$_GET['url'];

Kate Gregory
sumber
Mengapa menemukan kembali roda? Data ini jauh lebih mudah diakses!
Kenneth
Dan ada kerumitan tambahan jika permintaan asli diharapkan memiliki string kueri. Dalam keadaan saat ini, kode di atas hanya akan menimpa string kueri. Jika Anda menggabungkan string kueri ( QSAbendera) maka parameter string kueri berpotensi ditimpa (misalnya, jika Anda memerlukan urlparam pada permintaan awal) atau lebih buruk lagi, rentan terhadap serangan XSS.
MrWhite