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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
109
0
79 573
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

Всегда ли это полный URI?

Eli 11.11.2008 07:30

Как правило, вы можете столкнуться с проблемами с apache в Windows, но только для URI, которые не решаются.

Xenph Yan 11.11.2008 07:41

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

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

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

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

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

/news/local/345

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

Спасибо - это хорошая идея, но я использую их в предсистемной ловушке, которую необходимо запустить до того, как контроллер будет запущен.

Eli 11.11.2008 09:26
Ответ принят как подходящий

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

'PHP_SELF'

The filename of the currently executing script, relative to the document root. For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar would be /test.php/foo.bar. The __FILE__ constant contains the full path and filename of the current (i.e. included) file. If PHP is running as a command-line processor this variable contains the script name since PHP 4.3.0. Previously it was not available.

'SCRIPT_NAME'

Contains the current script's path. This is useful for pages which need to point to themselves. The __FILE__ constant contains the full path and filename of the current (i.e. included) file.

'REQUEST_URI'

The URI which was given in order to access this page; for instance, '/index.html'.

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

Скорее всего, речь идет не о документации PHP, а о CGI :) И там PATH_INFO задокументирован: tools.ietf.org/html/rfc3875#section-4 Но есть некоторые известные проблемы, которые Apache и nginx не всегда предоставляют этой переменной.

SimonSimCity 17.02.2012 12:53

Ответ Одина ниже добавляет полезные объяснения, дополненные примерами. Мне трудно понять, что представляют собой эти переменные в общем контексте с path_info, строкой запроса, некоторым перенаправлением, некоторыми псевдонимами в разных операционных системах, от CLI к SERVER и т. д.

user2066805 16.12.2015 01:35

-1 Просто как объяснение того, почему я проголосовал против: вся причина, по которой я пришел к этому посту, заключается в том, что документация не ясна. Ответ Odin ниже дает четкое объяснение различий между этими переменными. Мне кажется, что это недостаточный ответ, чтобы просто скопировать и вставить легко найденную, но при этом недостаточную документацию. Я считаю, что большинству людей пришлось бы уже посетить документацию, чтобы хотя бы узнать о списке элементов в переменной $ _SERVER, упомянутой выше.

dallin 15.08.2018 02:02

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

+1: «Пример - это не способ учиться, это единственный способ учиться». - Мне всегда приходится перепроверять этот материал, очень хорошее исследование ошибок 404. знак равно

Alix Axel 09.05.2010 21:44

+1: Первый раз в жизни я понял разницу. Они должны обновить документацию PHP вашим ответом

Marco Demaio 23.03.2011 17:40

Example1: [SCRIPT_NAME] => /test.php/ В конце не должно быть символа "/": Example1: [SCRIPT_NAME] => /test.php В любом случае это то, что я вижу в PHP 5.3.6. Хорошие примеры.

Dawid Ohia 21.03.2012 12:25

Вы правы, JohnM2, теперь я проверил PHP 5.4, и результат для URL /pinfo.php/first/second?third=fourth выглядит следующим образом: QUERY_STRING => третий = четвертый REQUEST_URI => /pinfo.php/first/second ? третий = четвертый SCRIPT_NAME => /pinfo.php PATH_INFO => / первый / второй

Odin 10.04.2012 16:24

Я тестировал это и на 5.2.17, и в конце / нет SCRIPT_NAME. Это похоже на PHP 5.2-5.4, учитывая редактирование ответа, чтобы отразить это.

Fabrício Matté 07.09.2012 06:11

Вы пропустили REQUEST_URI и PHP_SELF, здесь они отличаются, если вы запрашиваете example.com: [REQUEST_URI] => / и [PHP_SELF] => /index.php

icc97 19.12.2013 19:37

Это очень полезно, особенно часть обработки ошибок в Примере 4. Недавно я обнаружил, что некоторые программисты используют REQUEST_URI в качестве условий, а затем предоставляют другой верхний и нижний колонтитулы соответственно. Это работает в большинстве случаев, но будут проблемы со страницами 404/403. Я думаю, что лучший способ - использовать SCRIPT_NAME для получения РЕАЛЬНОЙ запрошенной страницы на Apache.

ChandlerQ 11.10.2014 10:07

Я знаю, что это не часть вопроса, но полезно упомянуть, что [REQUEST_URI] определяется до перезаписи URL, включая перезапись mod_dir, как указано @ icc97. [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] определяется после mod_dir и mod_rewrite, но до разрешения псевдонимов. Псевдонимы могут изменить полный путь URL (который PHP называет [PHP_SELF]) для получения [SCRIPT_FILENAME], который является фактическим сценарием в файловой системе. Чтобы быть немного более полным, давайте добавим, что сценарий может включать другие файлы, а __FILE__ является текущим файлом.

user2066805 19.12.2015 09:17

Пример 1 также говорит, что [REQUEST_URI] отличается от [SCRIPT_NAME], когда [PATH_INFO] не пустой. Это было понято, но явно не написано. Пример [REQUEST_URI] => /test.php/foo.bar, [SCRIPT_NAME] => /test.php

user2066805 19.12.2015 21:38

стоит отметить эту ошибку apache: bz.apache.org/bugzilla/show_bug.cgi?id=40102

Brad Kent 21.12.2018 06:49

Также стоит привести пример обхода доменов, так как они тоже различаются. Например, в http://example.com/something/../test.php REQUEST_URI будет /something/../test.php, а SCRIPT_NAME будет /test.php. :)

Jamie Robinson 26.04.2019 21:44

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

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

вместо? Тогда возьмите его с помощью $_GET['url'];

Зачем изобретать велосипед? Доступ к этим данным намного проще!

Kenneth 10.10.2011 04:22

И есть дополнительная сложность, если ожидается, что исходный запрос будет содержать строку запроса. В текущем состоянии приведенный выше код просто перезапишет строку запроса. Если вы объединяете строки запроса (флаг QSA), то параметры строки запроса потенциально могут быть перезаписаны (например, если вам нужен параметр url в первоначальном запросе) или, что еще хуже, быть уязвимыми для XSS-атак.

MrWhite 23.01.2017 16:25

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 ^(([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

Корень

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

Это было здорово. Спасибо за вашу помощь!

Gabriel Fair 29.04.2012 02:06

Этот ответ написан таким образом, что предполагает, что только перезапись URL-адреса может создать path_info, но, конечно, информацию о пути можно ввести непосредственно в исходный URL-адрес.

user2066805 25.12.2015 05:46

Пути 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, расположенные после имени скрипта, но перед строкой запроса.

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

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

Это хорошо. Вот мои комментарии. Во-первых, и $ _SERVER ['SCRIPT_NAME'], и $ _SERVER ['SCRIPT_FILENAME'] - это имя сценария, за исключением того, что последнее - после выполнения псевдонимов. Во-вторых, $ _SERVER ['PHP_SELF'] - это не сценарий, а сценарий + информация о пути. Опять же, $ _SERVER ['SCRIPT_NAME'] - это сценарий (перед псевдонимами). Наконец, полезно знать, на каком этапе, после или до правил перезаписи, после или до псевдонимов, определяются эти переменные. Смотрите мой ответ.

user2066805 16.12.2015 07:47

@ Dominic108 Я пересмотрел свой ответ на основе ваших предложений, немного прибрался и добавил раздел Порядок работы. Дайте мне знать, что вы думаете. Спасибо!

Beejor 17.12.2015 05:36

В вашем заказе вы должны поменять местами $_SERVER['SCRIPT_NAME'] и $_SERVER['PHP_SELF'], потому что mod_rewrite создает весь путь, то есть $_SERVER['PHP_SELF']. Далее происходит разделение. Обратите внимание, что псевдонимы также учитывают весь путь для определения имени файла сценария, но разделение, которое определило имя_сценария и путь_инфо, уже произошло, поэтому они не будут затронуты.

user2066805 17.12.2015 10:46

@ Dominic108 Я снова пересмотрел свой ответ. По какой-то причине ваше предложение по редактированию было отклонено, хотя, насколько мне известно, вы правы в том, что два моих элемента вышли из строя. Я не так хорошо знаком с псевдонимами, поэтому полагаюсь на ваш опыт в этой части. Еще раз спасибо!

Beejor 18.01.2016 04:44

К ответу Одина добавить очень мало. Я просто хотел предоставить полный пример от 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 в ответе Odin, что в файловой системе выполняется поиск, чтобы определить, существует ли файл. , но это актуально только в том случае, если файл не найден. Аналогично, mod_dir вызывает mod_alias для поиска в файловой системе, но это актуально только в том случае, если у вас есть псевдоним, например Alias \index.php \var\www\index.php, а запрос uri - это каталог.

Привет Dominic108, спасибо за доработку. Я действительно думаю, что полезно включить информацию о перезаписи. Для меня это подразумевалось, но для других это может быть не так интуитивно.

Beejor 17.12.2015 04:57

Если вы когда-нибудь забудете, какие переменные что делают, вы можете написать небольшой скрипт, который использует 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

Другие вопросы по теме