PHP_SELF vs PATH_INFO против SCRIPT_NAME и REQUEST_URI

Я создаю 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 видит символ подчеркивания и по какой-то причине делает его курсивом.

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

Документация 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, похоже, не документируется …

Некоторые практические примеры различий между этими переменными:
Пример 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?) это отличалось.

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

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 

корень

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) 

корень

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 ^(([az]{2})|(([az]{2})/)?(.*))$ index.php/$5 [NC,L,E=LANGUAGE:$2$4] 

или

 RewriteRule ^([az]{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 

корень

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 

Пути PHP

$_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 и даже не может соответствовать любому файлу
  • Текущий файл означает включенный файл сценария , а не любой скрипт, который включает его
  • Запрошенный файл означает файл сценария includeer , а не включенный
  • 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__ ссылается на путь к текущему файлу

Вы можете посмотреть в URI-класс и использовать $ this-> uri-> uri_string ()

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

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

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

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

 /news/local/345 

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

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

В ответ Одина очень мало добавить. Я просто хотел представить полный пример из 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 влияют на пути к системным файлам 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 запроса – это каталог.

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

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

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