PHP_SELF против 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 видит подчеркивание и почему-то выделяет его курсивом.
Обновлено: исправлены пробелы.
10 ответов
Документация 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):
[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
корень
[PHP_SELF] => /index.php
[PATH_INFO] IS NOT AVAILABLE (fallback to REQUEST_URI in your script)
[REQUEST_URI] => /
[QUERY_STRING] =>
Дорожка
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
Строка запроса
[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)
корень
[REQUEST_URI] => /
[QUERY_STRING] =>
Дорожка
[REQUEST_URI] => /test
[QUERY_STRING] => url=test
Строка запроса
[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
корень
[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
Дорожка
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /test
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] =>
язык
[PHP_SELF] => /index.php/
[PATH_INFO] => /
[REQUEST_URI] => /en
[QUERY_STRING] =>
[REDIRECT_LANGUAGE] => en
Языковой путь
[PHP_SELF] => /index.php/test
[PATH_INFO] => /test
[REQUEST_URI] => /en/test
[REDIRECT_LANGUAGE] => en
Строка запроса языка
[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
и может даже не совпадать ни с одним файлом - Текущий файл означает включенный файл сценария, а не любой сценарий, который его включает
- Запрашиваемый файл означает файл сценария включения, а не включенный
- URI - это HTTP-запрос
/index.php?foo=bar
перед перезаписью любого URL - Информация о пути - это любые дополнительные данные Apache, расположенные после имени скрипта, но перед строкой запроса
Порядок работы
- Клиент отправляет серверу HTTP-запрос
REQUEST_URI
- Сервер выполняет любые перезаписи URL из файлов.htaccess и т. Д., Чтобы получить
PHP_SELF
- Сервер отделяется
PHP_SELF
вSCRIPT_FILENAME
+PATH_INFO
- Сервер выполняет разрешение псевдонимов и преобразует весь URL-путь в системный путь к файлу, чтобы получить
SCRIPT_FILENAME
- Результирующий файл сценария может включать другие, где
__FILE__
ссылается на путь к текущему файлу
Вы можете заглянуть в класс URI и использовать $this->uri->uri_string()
Возвращает строку с полным URI.
Например, если это ваш полный URL:
http://example.com/index.php/news/local/345
Функция вернет это:
/news/local/345
Или вы можете использовать сегменты для детализации определенных областей без необходимости разбирать значения парсинга / регулярного выражения.
Есть очень мало, чтобы добавить к ответу Одина. Я просто хотел представить полный пример от 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 является каталогом.
Лично я пользуюсь $REQUEST_URI
поскольку он ссылается на введенный URI, а не на местоположение на диске сервера.
Если вы когда-нибудь забудете, какие переменные делают что-то, вы можете написать небольшой скрипт, который использует 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
простой-простой ответ:
предполагатьscheme://host/path/script.php
послеscript.php
будет две возможности:
1- строка запроса типаscheme://host/path/script.php?qs=a
2- дополнительная информация о пути, напримерscheme://host/path/script.php/more/path
теперь у нас есть очень простые правила:
Сделайте резервную копию на секунду, вы выбрали неправильный подход для начала. Почему бы просто не сделать это
RewriteEngine on
RewriteCond $1 !^(images|inc|favicon\.ico|index\.php|robots\.txt)
RewriteRule ^(.*)$ /index.php?url=$1 [L]
вместо? Затем возьмите его $_GET['url'];