PHP_SELF - PATH_INFO - SCRIPT_NAME - REQUEST_URI


105

CodeIgniter'da bir PHP uygulaması oluşturuyorum. CodeIgniter ana kontrolöre tüm istekleri gönderir: index.php. Ancak, index.phpURI'de görmeyi sevmiyorum . Örneğin, http://www.example.com/faq/whateveradresine yönlendirilecek http://www.example.com/index.php/faq/whatever. Bir komut dosyasının adresinin ne olduğunu bilmesi için güvenilir bir yola ihtiyacım var, böylece navigasyonla ne yapacağını bilecek. Ben kullandım mod_rewriteCodeIgniter belgelendirmesi olarak.

Kural aşağıdaki gibidir:

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

Normalde kontrol ederdim php_selfama bu durumda her zaman olur index.php. Ben mal alabilirsiniz REQUEST_URI, PATH_INFOvb ama en güvenilir olacağı karar vermeye çalışıyorum. Bilen var mı (ya da nerede bulacağını biliyor) arasındaki gerçek fark PHP_SELF, PATH_INFO, SCRIPT_NAMEve REQUEST_URI? Yardımınız için teşekkürler!

Not : SO alt çizgiyi gördüğünden ve bazı nedenlerden dolayı italik yaptığından boşluk eklemem gerekti.

Güncellendi : Boşluklar düzeltildi.

Yanıtlar:


50

PHP belgelerine farkı söyleyebilir:

'PHP_SELF'

O anda çalıştırılan betiğin belge köküne göre dosya adı. Örneğin, http://example.com/test.php/foo.bar adresindeki bir komut dosyasındaki $ _SERVER ['PHP_SELF'] , /test.php/foo.bar olacaktır . __FILE__ sabit akımın tam yolunu ve dosya adını içeren dosyayı (yani dahil). PHP bir komut satırı işlemcisi olarak çalışıyorsa, bu değişken PHP 4.3.0'dan sonraki betik adını içerir. Daha önce mevcut değildi.

"SCRIPT_NAME"

Mevcut betiğin yolunu içerir. Bu, kendilerini göstermesi gereken sayfalar için kullanışlıdır. __FILE__ sabit akımın tam yolunu ve dosya adını içeren dosyayı (yani dahil).

"REQUEST_URI"

Bu sayfaya erişmek için verilen URI; örneğin, '/index.html' .

PATH_INFO belgelenmemiş gibi görünüyor ...


3
Bu büyük olasılıkla PHP dokümantasyonuyla ilgili değil, CGI ile ilgilidir :) Ve orada PATH_INFO belgelenmiştir: tools.ietf.org/html/rfc3875#section-4 Ancak Apache ve nginx'in her zaman bu değişkeni vermediği bilinen bazı sorunlar vardır.
SimonSimCity

1
Odin'in aşağıdaki cevabı, örneklerle tamamlanan faydalı açıklamalar ekliyor. Bu değişkenlerin genel bir bağlamda bir path_info, bir sorgu dizesi, bazı yeniden yönlendirme, bazı takma adlar, farklı işletim sistemlerinde, CLI vs SERVER vb.

4
-1 Neden olumsuz oy kullandığıma dair bir açıklama olarak: Bu gönderiye gelmemin tüm nedeni belgelerin net olmamasıdır. Odin'in aşağıdaki cevabı, bu değişkenler arasındaki farkların net bir açıklamasını sağlıyor. Kolayca bulunan ancak aynı zamanda yetersiz dokümantasyonun sadece kopyalayıp yapıştırmanın yetersiz bir cevap olduğunu düşünüyorum. Sanırım çoğu insan, yukarıda bahsedilen $ _SERVER değişkenindeki öğelerin listesi hakkında bilgi sahibi olmak için belgeleri zaten ziyaret etmek zorunda kalacaktı.
dallin

230

Bu değişkenler arasındaki farkların bazı pratik örnekleri:
Örnek 1. PHP_SELF, SCRIPT_NAME'den yalnızca istenen url biçiminde olduğunda farklıdır :
http://example.com/test.php/foo/bar

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

(PATH_INFO mantıklı bilgiler içerdiğinde tek durum bu gibi görünüyor [PATH_INFO] => / foo / bar) Not: Bu, bazı eski PHP sürümlerinde (<= 5.0?) farklıydı.

Örnek 2. REQUEST_URI, boş olmayan bir sorgu dizesi girildiğinde SCRIPT_NAME'den farklıdır:
http://example.com/test.php?foo=bar

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

Örnek 3. Sunucu tarafı yeniden yönlendirme etkinken REQUEST_URI SCRIPT_NAME'den farklıdır (örneğin apache'de mod_rewrite):

http://example.com/test.php

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

Örnek 4. REQUEST_URI, komut dosyalarıyla HTTP hatalarını işlerken SCRIPT_NAME'den farklıdır.
Apache yönergesi ErrorDocument 404 /404error.php
http://example.com/test.php kullanılarak

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

Özel hata sayfalarını kullanan IIS sunucusunda
http://example.com/test.php

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

21
+1, "Örnek bir öğrenme yolu değildir, öğrenmenin tek yolu budur." - Bu şeyleri her zaman yeniden kontrol etmem gerekiyor, 404 hataları üzerine çok güzel araştırmalar. =)
Alix Axel

16
+1: Hayatımda ilk kez farkı anladım. PHP belgelerini cevabınızla güncellemelidirler
Marco Demaio

Örnek1: [SCRIPT_NAME] => /test.php/ Sonunda "/" olmamalıdır: Örnek1: [SCRIPT_NAME] => /test.php Her neyse PHP 5.3.6'da gördüğüm şey bu. Güzel örnekler.
Dawid Ohia

Doğru JohnM2, şimdi PHP 5.4 üzerinde kontrol ettim ve /pinfo.php/first/second?third=fourth URL'sinin sonucu aşağıdaki gibidir: QUERY_STRING => third = dördüncü REQUEST_URI => /pinfo.php/first/second ? third = dördüncü SCRIPT_NAME => /pinfo.php PATH_INFO => / birinci / saniye
Odin

Bunu 5.2.17'de de test ettim /ve sonunda yok SCRIPT_NAME. Bu, yanıtın bunu yansıtacak şekilde düzenlenmesi düşünüldüğünde, PHP 5.2-5.4'te tutarlı görünüyor.
Fabrício Matté

24

PATH_INFO yalnızca şu şekilde htaccess kullanıldığında kullanılabilir:

örnek 1

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

Aynı kalmak

[SCRIPT_NAME] => /index.php

Kök

http://domain.com/

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

Yol

http://domain.com/test

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

Sorgu Dizesi

http://domain.com/test?123

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

Örnek 2

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

Aynı kalmak

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

Kök

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Yol

http://domain.com/test

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

Sorgu Dizesi

http://domain.com/test?123

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

Örnek 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]

veya

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]

Aynı kalmak

[SCRIPT_NAME] => /index.php

Kök

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

Yol

http://domain.com/test

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

Dil

http://domain.com/en

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

Dil yolu

http://domain.com/en/test

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

Dil Sorgu dizesi

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

Bu harikaydı. Yardımınız için teşekkürler!
Gabriel Fair

1
Bu cevap, yalnızca url yeniden yazma işleminin bir yol bilgisi oluşturabileceğini, ancak elbette yol bilgisinin doğrudan orijinal URL'ye girilebileceğini ima edecek şekilde yazılmıştır.

12

PHP Yolları

    $_SERVER['REQUEST_URI']    = Web yolu, istenen URI
    $_SERVER['PHP_SELF']    = Web yolu, istenen dosya + yol bilgisi
    $_SERVER['SCRIPT_NAME']    = Web yolu, istenen dosya
    $_SERVER['SCRIPT_FILENAME']   = Dosya yolu, istenen dosya
    __FILE__    = Dosya yolu, geçerli dosya

Nerede

  • Dosya yolu , takma ad çözümlemesinden sonra olduğu gibi bir sistem dosyası yoludur/var/www/index.php
  • Web yolu , from gibi bir sunucu belge yoludur ve herhangi bir dosyayla eşleşmeyebilir bile/index.phphttp://foo.com/index.php
  • Geçerli dosya , dahil edilen komut dosyası anlamına gelir , onu içeren herhangi bir komut dosyası değil
  • İstenen dosya , dahil edilen komut dosyası anlamına gelir , dahil edilen değil
  • URI , herhangi bir URL yeniden yazmadan önce olduğu gibi HTTP isteğidir/index.php?foo=bar
  • Yol bilgisi , komut dosyası adından sonra, ancak sorgu dizesinden önce bulunan fazladan Apache verileridir.

Operasyon Sırası

  1. İstemci sunucuya bir HTTP isteği gönderir REQUEST_URI
  2. Sunucu , .htaccess dosyalarından, vb. Herhangi bir URL yeniden yazma işlemi gerçekleştirir .PHP_SELF
  3. Sunucu PHP_SELF, SCRIPT_FILENAME+PATH_INFO
  4. Sunucu gerçekleştirdiği takma çözünürlük ve dönüşüm tüm url yolunu a sistem dosyası yolu almak içinSCRIPT_FILENAME
  5. Ortaya çıkan komut dosyası __FILE__, geçerli dosyanın yoluna atıfta bulunan başkalarını içerebilir

Bu iyi. İşte yorumlarım. İlk olarak, hem $ _SERVER ['SCRIPT_NAME'] hem de $ _SERVER ['SCRIPT_FILENAME'] komut dosyası adıdır, tek fark, takma adlar çalıştırıldıktan sonra sonradır. İkinci olarak, $ _SERVER ['PHP_SELF'] komut dosyası değil, komut dosyası + yol bilgisidir. Yine, $ _SERVER ['SCRIPT_NAME'] komut dosyasıdır (takma adlardan önce). Son olarak, bu değişkenlerin yeniden yazma kurallarından sonra veya öncesinde, diğer adlardan sonra veya öncesinde hangi aşamada tanımlandığını bilmek yararlıdır. Cevabımı gör.

@ Dominic108 Önerilerinize göre cevabımı revize ettim, işleri biraz düzelttim ve bir İşlem Sırası bölümü ekledim. Ne düşündüğü söyle. Teşekkürler!
Beejor

Siparişinize göre, değiştirmelisiniz $_SERVER['SCRIPT_NAME']ve   $_SERVER['PHP_SELF']mod_rewrite tüm yolu yarattığı için, yani $_SERVER['PHP_SELF']. Ayrılık daha sonra gerçekleşir. Diğer adların, komut dosyası dosya adını tanımlamak için tüm yolu da dikkate aldığını, ancak komut dosyası_adı ve yol_bilgisini tanımlayan ayrımın daha önce gerçekleştiğini ve bu nedenle etkilenmeyeceklerini unutmayın.

@ Dominic108 Cevabımı tekrar gözden geçirdim. Bazı nedenlerden dolayı düzenleme teklifiniz reddedildi, ancak bildiğim kadarıyla, öğelerimden ikisinin bozuk olduğu konusunda haklısınız. Takma adlara aşina değilim, bu yüzden bu bölüm için uzmanlığınıza güveniyorum. Tekrar teşekkürler!
Beejor

5

URI Sınıfına bakmak ve $ this-> uri-> uri_string () kullanmak isteyebilirsiniz.

Tam URI ile bir dize döndürür.

Örneğin, tam URL'niz buysa:

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

İşlev şunu döndürür:

/news/local/345

Veya ayrıştırma / normal ifade değerleri bulmak zorunda kalmadan belirli alanları ayrıntılandırmak için segmentlerden yararlanabilirsiniz.


Teşekkürler - bu iyi bir fikir, ancak bunları, denetleyici çalışmadan önce çalışması gereken bir ön sistem kancasında kullanıyorum.
Eli

4

Kişisel $REQUEST_URIolarak, sunucunun diskindeki konumu değil, girilen URI'yi referans aldığı için kullanıyorum .


Her zaman tam URI midir?
Eli

Tipik olarak, pencerelerde apache ile ilgili sorunlarla karşılaşabilirsiniz, ancak bu yalnızca çözülmeyen URI'ler içindir.
Xenph Yan

4

Odin'in cevabına eklenecek çok az şey var. URL yeniden yazma ve takma adların etkilerini göstermek için HTTP isteğinden dosya sistemindeki gerçek dosyaya eksiksiz bir örnek vermeyi düşündüm. Dosya sisteminde komut /var/www/test/php/script.phpolduğunu

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

nerede /var/www/test/php/script_included.phpolduğunu

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

ve /var/www/test/.htaccess olduğu

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

ve Apache yapılandırma dosyası takma adı içerir

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

ve http isteği

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

Çıktı olacak

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

Aşağıdaki her zaman tutar

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

Mod_rewrite, mod_dir, ErrorDocument yeniden yazma veya herhangi bir URL yeniden yazma biçimi yoksa, ayrıca

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

Adlar sistem dosya yollarını etkileyen SCRIPT_FILENAMEve __FILE__aşağıdaki istisnaları inceleyin -, önce değil tanımlanır URL yolları. Takma adlar, dahil tüm URL yolunu kullanabilir PATH_INFO. SCRIPT_NAMEVe arasında hiç bağlantı olamaz SCRIPT_FILENAME.

URL yolu [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] tanımlandığında takma adların çözülmediği tam olarak kesin değildir , çünkü takma adlar dosya sistemini arar olarak kabul edilir ve Odin'in cevabındaki örnek 4'ten dosyanın var olup olmadığını belirlemek için dosya sisteminin arandığını biliyoruz. ancak bu, yalnızca dosya bulunamadığında geçerlidir. Benzer şekilde, mod_dir mod_alias'ı dosya sistemini aramak için çağırır, ancak bu yalnızca gibi bir takma adınız varsa Alias \index.php \var\www\index.phpve istek uri'si bir dizinse geçerlidir .


Merhaba Dominic108, revizyon için teşekkürler. Yeniden yazma bilgisini dahil etmenin yararlı olduğunu düşünüyorum. Bana göre ima edildi, ancak diğerleri için o kadar sezgisel olmayabilir.
Beejor

1

Hangi değişkenlerin ne yaptığını unutursanız, phpinfo () kullanan küçük bir betik yazabilir ve onu bir sorgu dizesi olan bir URL'den çağırabilirsiniz. Sunucu yazılımı kurulumları, PHP'nin döndürdüğü değişkenleri sunduğundan, sunucu yapılandırma dosyasındaki yeniden yazmaların beklenenden farklı sonuçlara neden olması durumunda makinenin çıktısını kontrol etmek her zaman iyi bir fikirdir. Şunun gibi kaydedin _inf0.php:

<?php
    $my_ip = '0.0.0.0';

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

Sonra arardın /_inf0.php?q=500


-1

Bir saniye yedekleyin, başlangıçta yanlış yaklaşımı izlediniz. Neden bunu yapmıyorsun

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

yerine? O zaman yakala$_GET['url'];


Neden tekerleği yeniden icat etmelisiniz? Bu verilere çok daha kolay erişilebilir!
Kenneth

Ve orijinal isteğin bir sorgu dizesine sahip olması bekleniyorsa ek karmaşıklık vardır. Mevcut durumunda, yukarıdaki kod basitçe sorgu dizesinin üzerine yazacaktır. Sorgu dizelerini ( QSAbayrak) birleştirirseniz, sorgu dizesi parametrelerinin üzerine yazılabilir (örneğin, urlilk istekte bir parametreye ihtiyacınız varsa ) veya daha kötüsü, XSS saldırılarına karşı savunmasız olabilir.
MrWhite
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.