PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

我正在用 CodeIgniter 构建一个 PHP 应用程序。CodeIgniter 将所有请求发送到主控制器: index.php。但是,我不喜欢在 URI 中看到 index.php。例如,http://www.example.com/faq/whatever将路由到 http://www.example.com/index.php/faq/whatever。我需要一个可靠的方式,让脚本知道它的地址是什么,这样它就会知道如何处理导航。根据 CodeIgniter 文档,我使用了 mod_rewrite

规则如下:

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

通常,我只检查 php_self,但在这种情况下,它总是 index.php。我可以得到它从 REQUEST_URIPATH_INFO等,但我试图决定哪一个将是最可靠的。有人知道(或知道在哪里找到) PHP_SELFPATH_INFOSCRIPT_NAMEREQUEST_URI之间的真正区别吗?谢谢你的帮助!

注意 : 我必须添加空格,因为 SO 看到了下划线,并且由于某种原因使其变为斜体。

更新 : 修复空格。

84985 次浏览

我个人使用 $REQUEST_URI,因为它引用的是 URI 输入,而不是服务器光盘上的位置。

您可能需要查看 URI 类并使用 $this-> uri-> uri _ string ()

返回具有完整 URI 的字符串。

例如,如果这是你的完整网址:

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

The function would return this:

/news/local/345

或者您可以使用段来深入挖掘特定区域,而不必提供解析/正则表达式值

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 文件 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’

包含当前脚本的路径。这对于需要指向自己的页面很有用。文件常量包含当前文件(即包含的)的完整路径和文件名。

'REQUEST_URI'

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

PATH _ INFO 似乎没有文档记录..。

Some practical examples of the differences between these variables:
例子一。 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 is different from SCRIPT_NAME when server-side redirecton is in effect (for example mod_rewrite on apache):

http://example.com/test.php

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

例子4。 REQUEST _ URI 在使用脚本处理 HTTP 错误时与 SCRIPT _ NAME 不同。
使用 apache 指令 ErrorDocument 404/404 error. 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

等一下,你一开始就采取了错误的方法,为什么不这样做呢

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

然后用 $_GET['url'];抓住它

只有像下面这样使用 htaccess 才能使用 PATH_INFO:

例子一

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

Example 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

Example 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]

Remains the same

[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']    = Web 路径,请求的 URI
  $_SERVER['PHP_SELF']    = Web 路径,请求的文件 + 路径信息
  $_SERVER['SCRIPT_NAME']    = Web 路径,请求的文件
文件路径,请求的文件
  __FILE__    = 文件路径,当前文件 < br/>

在哪里

  • File path is a system file path like /var/www/index.php, after alias resolution
  • Web path is a server document path like /index.php from http://foo.com/index.php,甚至可能不匹配任何文件
  • 当前文件 意味着 包含的脚本文件,而不是包含它的任何脚本
  • 请求的文件 表示 the includer script file,而不是包含的文件
  • URI HTTP 请求,就像 /index.php?foo=bar一样,在任何 URL 重写之前
  • Path info 是位于脚本名称之后但查询字符串之前的任何额外 Apache 数据

行动命令

  1. 客户端向服务器发送 HTTP 请求 REQUEST_URI
  2. 服务器执行任何来自.htaccess 文件的 URL 重写等来获取 PHP_SELF
  3. 服务器将 PHP_SELF分成 SCRIPT_FILENAME + PATH_INFO
  4. 服务器执行 alias resolution并将整个 网址路径转换为 系统文件路径系统文件路径以获得 SCRIPT_FILENAME
  5. 生成的脚本文件可能包含其他脚本文件,其中 __FILE__引用当前文件的路径

There is very little to add to Odin's answer. I just felt to provide a complete example from the HTTP request to the actual file on the file system to illustrate the effects of URL rewriting and aliases. On the file system the script /var/www/test/php/script.php is

<?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_INFOSCRIPT_NAMESCRIPT_FILENAME之间可能根本没有连接。

在定义 URL 路径 [PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO]时,别名没有得到解析,这并不完全准确,因为别名被认为是用来搜索文件系统的,我们从 Odin 的答案的例子4中知道,搜索文件系统是为了确定文件是否存在,但这只有在找不到文件时才有意义。类似地,mod _ dir 调用 mod _ alias 来搜索文件系统,但是只有当您有一个别名(如 Alias \index.php \var\www\index.php)并且请求 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