PHP_SELF против PATH_INFO против SCRIPT_NAME против REQUEST_URI - PullRequest
98 голосов
/ 11 ноября 2008

Я строю PHP-приложение в CodeIgniter. CodeIgniter отправляет все запросы на главный контроллер: index.php. Тем не менее, я не люблю видеть index.php в URI. Например, http://www.example.com/faq/whatever будет направлено на http://www.example.com/index.php/faq/whatever. Мне нужен надежный способ для скрипта узнать его адрес, чтобы он знал, что делать с навигацией. Я использовал mod_rewrite согласно документации CodeIgniter.

Правило следующее:

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

Обычно я бы просто проверил php_self, но в этом случае это всегда index.php. Я могу получить его от REQUEST_URI, PATH_INFO и т. Д., Но я пытаюсь решить, какой из них будет наиболее надежным. Кто-нибудь знает (или знает, где найти) реальную разницу между PHP_SELF, PATH_INFO, SCRIPT_NAME и REQUEST_URI? Спасибо за вашу помощь!

Примечание : Мне пришлось добавить пробелы, так как SO видит подчеркивание и почему-то выделяет его курсивом.

Обновлено : исправлены пробелы.

Ответы [ 9 ]

216 голосов
/ 28 ноября 2008

Некоторые практические примеры различий между этими переменными:
Пример 1 PHP_SELF отличается от SCRIPT_NAME только , когда запрошенный URL находится в форме:
http://example.com/test.php/foo/bar

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

(кажется, это единственный случай, когда PATH_INFO содержит разумную информацию [PATH_INFO] => / foo / bar) Примечание: раньше это отличалось в некоторых старых версиях PHP (<= 5.0?). </p>

Пример 2. REQUEST_URI отличается от SCRIPT_NAME, когда вводится непустая строка запроса:
http://example.com/test.php?foo=bar

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

Пример 3. REQUEST_URI отличается от SCRIPT_NAME, когда действует перенаправление на стороне сервера (например, mod_rewrite на apache):

http://example.com/test.php

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

Пример 4. REQUEST_URI отличается от SCRIPT_NAME при обработке ошибок HTTP с помощью сценариев.
Использование директивы apache ErrorDocument 404 /404error.php
http://example.com/test.php

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

На сервере IIS с использованием пользовательских страниц ошибок
http://example.com/test.php

[SCRIPT_NAME] => /404error.php
[REQUEST_URI] => /404error.php?404;http://example.com/test.php
50 голосов
/ 11 ноября 2008

Документация PHP может подсказать разницу:

'PHP_SELF'

Имя файла исполняемого в данный момент скрипта относительно корня документа. Например, $ _ SERVER ['PHP_SELF'] в скрипте по адресу http://example.com/test.php/foo.bar будет / test.php / foo.bar . Константа __ FILE __ содержит полный путь и имя файла текущего (т.е. включенного) файла. Если PHP работает как процессор командной строки, эта переменная содержит имя сценария начиная с PHP 4.3.0. Ранее это было недоступно.

SCRIPT_NAME '

Содержит путь текущего скрипта. Это полезно для страниц, которые должны указывать на себя. Константа __ FILE __ содержит полный путь и имя файла текущего (т.е. включенного) файла.

'REQUEST_URI'

URI, который был дан для доступа к этой странице; например, '/ index.html' .

PATH_INFO, похоже, не задокументировано ...

20 голосов
/ 07 марта 2012

PATH_INFO доступно только при использовании htaccess следующим образом:

Пример 1

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

Остается прежним

[SCRIPT_NAME] => /index.php

Root

http://domain.com/

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

Путь

http://domain.com/test

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

Строка запроса

http://domain.com/test?123

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

Пример 2

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

Остается прежним

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

Root

http://domain.com/

[REQUEST_URI]  => /
[QUERY_STRING] => 

Путь

http://domain.com/test

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

Строка запроса

http://domain.com/test?123

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

Пример 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]

или

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]

Остается прежним

[SCRIPT_NAME] => /index.php

Root

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

Путь

http://domain.com/test

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

Язык

http://domain.com/en

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

Языковой путь

http://domain.com/en/test

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

Строка языкового запроса

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
8 голосов
/ 10 апреля 2015

PHP Paths

  $_SERVER['REQUEST_URI']    = веб-путь, запрошенный URI
  $_SERVER['PHP_SELF']    = веб-путь, запрашиваемый файл + информация о пути
  $_SERVER['SCRIPT_NAME']    = веб-путь, запрошенный файл
  $_SERVER['SCRIPT_FILENAME']   = Путь к файлу, запрашиваемый файл
  __FILE__    = Путь к файлу, текущий файл

Где

  • Путь к файлу - это системный путь к файлу , такой как /var/www/index.php, после разрешения псевдонима
  • Веб-путь - это серверный путь к документу как /index.php из http://foo.com/index.php и может даже не совпадать ни с одним файлом
  • Текущий файл означает включенный файл сценария , а не любой сценарий, который его включает
  • Запрашиваемый файл означает файл сценария включения , а не включенный
  • URI - это HTTP-запрос , как /index.php?foo=bar, перед перезаписью любого URL
  • Информация о пути - это любые дополнительные данные Apache, расположенные после имени скрипта, но перед строкой запроса

Порядок работы

  1. Клиент отправляет серверу HTTP-запрос REQUEST_URI
  2. Сервер выполняет любые перезаписи URL из файлов .htaccess и т. Д., Чтобы получить PHP_SELF
  3. Сервер разделяет PHP_SELF на SCRIPT_FILENAME + PATH_INFO
  4. Сервер выполняет разрешение псевдонима и преобразует весь путь URL в путь к системному файлу , чтобы получить SCRIPT_FILENAME
  5. Результирующий файл сценария может включать другие, где __FILE__ обозначает путь к текущему файлу
4 голосов
/ 11 ноября 2008

Возможно, вы захотите заглянуть в URI-класс и использовать $ this-> uri-> uri_string ()

Возвращает строку с полным URI.

Например, если это ваш полный URL:

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

Функция вернет это:

/news/local/345

Или вы можете использовать сегменты для детализации определенных областей без необходимости разбирать значения парсинга / регулярного выражения

3 голосов
/ 16 декабря 2015

Очень мало что можно добавить к ответу Одина. Я просто хотел представить полный пример от HTTP-запроса до реального файла в файловой системе, чтобы проиллюстрировать эффекты перезаписи URL-адресов и псевдонимов. В файловой системе сценарий /var/www/test/php/script.php равен

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

, где /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>";  
?>

и /var/www/test/.htaccess - это

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

и файл конфигурации Apache включает псевдоним

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

и http-запрос

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

Вывод будет

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

Следующее всегда имеет место

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

Если нет mod_rewrite, mod_dir, перезаписи ErrorDocument или какой-либо формы перезаписи URL, у нас также есть

REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

Псевдонимы влияют на пути к системным файлам SCRIPT_FILENAME и __FILE__, а не на пути URL, которые определены ранее - см. Исключения ниже. Псевдонимы могут использовать весь путь URL, включая PATH_INFO. Между SCRIPT_NAME и SCRIPT_FILENAME не может быть никакой связи.

Не совсем точно, что псевдонимы не разрешаются во время определения пути URL [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO], потому что псевдонимы рассматриваются для поиска в файловой системе, и мы знаем из примера 4 в ответе Одина, что файловая система ищется в определить, существует ли файл, но это актуально, только если файл не найден. Аналогично, mod_dir вызывает mod_alias для поиска в файловой системе, но это актуально только в том случае, если у вас есть псевдоним, такой как Alias \index.php \var\www\index.php, а запрос uri является каталогом.

3 голосов
/ 11 ноября 2008

Лично я использую $REQUEST_URI, поскольку он ссылается на введенный URI, а не на местоположение на диске сервера.

0 голосов
/ 23 июля 2018

Если вы когда-нибудь забудете, какие переменные что-то делают, вы можете написать небольшой скрипт, который использует phpinfo () и вызвать его по URL-адресу со строкой запроса. Поскольку при установке серверного программного обеспечения присутствуют переменные, которые возвращает PHP, всегда полезно проверить выходные данные компьютера на случай, если перезапись в файле конфигурации сервера приведет к результатам, отличным от ожидаемых. Сохранить как что-то вроде _inf0.php:

<?php
    $my_ip = '0.0.0.0';

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

Тогда вы бы позвонили /_inf0.php?q=500

0 голосов
/ 28 декабря 2008

Резервное копирование в секунду, вы выбрали неправильный подход для начала. Почему бы просто не сделать это

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

вместо этого? Затем возьмите его с $_GET['url'];

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...