PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

PHP_SELF vs PATH_INFO vs SCRIPT_NAME vs REQUEST_URI

提问人:Eli 提问时间:11/11/2008 最后编辑:imlouisrussellEli 更新时间:6/26/2023 访问量:87174

问:

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

规则如下:

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

通常,我只会检查 ,但在这种情况下,它总是.我可以从 、 等处获取它,但我正在尝试决定哪个最可靠。有谁知道(或知道在哪里可以找到)、、、和之间的真正区别?感谢您的帮助!php_selfindex.phpREQUEST_URIPATH_INFOPHP_SELFPATH_INFOSCRIPT_NAMEREQUEST_URI

注意:我不得不添加空格,因为 SO 会看到下划线,并且出于某种原因将其设为斜体。

更新:修复了空格。

网址 PHP的 代码点燃器

评论


答:

4赞 Xenph Yan 11/11/2008 #1

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

评论

0赞 Eli 11/11/2008
它始终是完整的 URI 吗?
0赞 Xenph Yan 11/11/2008
通常,您可能会遇到 Windows 上的 apache 问题,但仅适用于无法解决的 URI。
5赞 Adam 11/11/2008 #2

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

返回包含完整 URI 的字符串。

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

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

该函数将返回以下内容:

/news/local/345

或者,您可以利用这些段来向下钻取特定区域,而不必提出解析/正则表达式值

评论

0赞 Eli 11/11/2008
谢谢 - 这是个好主意,但我在预系统钩子中使用它们,该钩子需要在控制器启动并运行之前运行。
54赞 Paige Ruten 11/11/2008 #3

PHP 文档可以告诉你区别:

“PHP_SELF”

当前正在执行的脚本的文件名,相对于文档根目录。例如,http://example.com/test.php/foo.bar 地址的脚本中的 $_SERVER['PHP_SELF'] 将为 /test.php/foo.bar__FILE__常量包含当前(即包含的)文件的完整路径和文件名。如果 PHP 作为命令行处理器运行,则此变量包含自 PHP 4.3.0 起的脚本名称。以前它不可用。

“SCRIPT_NAME”

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

“REQUEST_URI”

为访问此页面而提供的 URI;例如,“/index.html”

“PATH_INFO”

包含客户端提供的任何路径名信息,该路径名位于实际脚本文件名之后,但在查询字符串之前(如果可用)。例如,如果当前脚本是通过 URI http://www.example.com/php/path_info.php/some/stuff?foo=bar 访问的,则 $_SERVER['PATH_INFO'] 将包含 /some/stuff

评论

3赞 SimonSimCity 2/17/2012
这很可能不是关于PHP文档,而是关于CGI:)PATH_INFO记录了: tools.ietf.org/html/rfc3875#section-4 但是有一些已知的问题,Apache 和 nginx 并不总是给出这个变量。
1赞 12/16/2015
奥丁在下面的回答增加了有用的解释,并辅以示例。我发现很难理解这些变量在具有path_info、查询字符串、一些重定向、一些别名、在不同操作系统上、从 CLI 与 SERVER 等的一般上下文中代表什么。
7赞 dallin 8/15/2018
-1 作为我为什么投反对票的解释:我来这篇文章的全部原因是因为文档不清楚。奥丁在下面的回答清楚地解释了这些变量之间的差异。我觉得仅复制和粘贴很容易找到但文档也不足是不够的。我相信大多数人必须已经访问了文档才能了解上面提到的 $_SERVER 变量中的元素列表。
252赞 Odin 11/29/2008 #4

这些变量之间差异的一些实际示例:
示例 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不同(例如,在 Apache 上mod_rewrite):

http://example.com/test.php

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

例 4. 使用脚本处理 HTTP 错误时,REQUEST_URI 与SCRIPT_NAME不同。
使用 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

评论

30赞 Alix Axel 5/10/2010
+1,“示例不是学习的方式,而是唯一的学习方式。 - 我总是要重新检查这些东西,对 404 错误进行了很好的研究。=)
20赞 Marco Demaio 3/23/2011
+1:我有生以来第一次明白了其中的区别。他们应该用你的答案更新PHP文档
0赞 Dawid Ohia 3/21/2012
示例1: [SCRIPT_NAME] => /test.php/ 末尾不应该有“/”: 示例1: [SCRIPT_NAME] => /test.php 无论如何,这就是我在 PHP 5.3.6 中看到的。很好的例子。
0赞 Odin 4/10/2012
你是对的JohnM2,我现在已经检查了PHP 5.4,URL /pinfo.php/first/second?third=fourth的结果如下: QUERY_STRING => 第三=第四 REQUEST_URI => /pinfo.php/第一/第二?第三=第四 SCRIPT_NAME => /pinfo.php PATH_INFO => /第一/第二
0赞 Fabrício Matté 9/7/2012
我也在 5.2.17 上测试过这个,但 .这在 PHP 5.2-5.4 中似乎是一致的,然后考虑编辑答案以反映这一点。/SCRIPT_NAME
-1赞 Mark 12/28/2008 #5

备份一秒钟,你一开始就采取了错误的方法。为什么不这样做

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

相反?然后用$_GET['url'];

评论

0赞 Kenneth 10/10/2011
为什么要重新发明轮子?这些数据更容易访问!
0赞 MrWhite 1/23/2017
如果原始请求应具有查询字符串,则会更加复杂。在当前状态下,上述代码将简单地覆盖查询字符串。如果合并查询字符串 ( flag),则查询字符串参数可能会被覆盖(例如,如果您在初始请求中需要参数),或者更糟的是,容易受到 XSS 攻击。QSAurl
27赞 Mike 3/7/2012 #6

PATH_INFO仅在使用 HTTecess 时可用,如下所示:

示例 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

评论

1赞 12/25/2015
这个答案的编写方式表明,只有 url 重写才能创建path_info,但是,当然,路径信息可以直接输入到原始 URL 中。
15赞 Beejor 4/10/2015 #7

PHP 路径

= Web 路径,请求的 URI
= Web 路径,请求的文件 + 路径信息
= Web 路径,请求的文件
= 文件路径,请求的文件
= 文件路径,当前文件
  $_SERVER['REQUEST_URI']     $_SERVER['PHP_SELF']     $_SERVER['SCRIPT_NAME']     $_SERVER['SCRIPT_FILENAME']    __FILE__   

哪里

  • 文件路径是别名解析后的系统文件路径,如/var/www/index.php
  • Web 路径是类似于 from 的服务器文档路径,甚至可能与任何文件都不匹配/index.phphttp://foo.com/index.php
  • 当前文件是指包含的脚本文件,而不是包含它的任何脚本
  • 请求的文件是指包含脚本文件,而不是包含的文件
  • URI 是 HTTP 请求,例如 ,在任何 URL 重写之前/index.php?foo=bar
  • 路径信息是位于脚本名称之后但查询字符串之前的任何额外 Apache 数据

操作顺序

  1. 客户端向服务器发送 HTTP 请求 REQUEST_URI
  2. 服务器从 .htaccess 文件等执行任何 URL 重写,以获取PHP_SELF
  3. 服务器分为PHP_SELFSCRIPT_FILENAME + PATH_INFO
  4. 服务器执行别名解析,并将整个 url 路径转换为要获取的系统文件路径SCRIPT_FILENAME
  5. 生成的脚本文件可以包括其他脚本文件,其中引用当前文件的路径__FILE__

评论

0赞 12/16/2015
这很好。这是我的评论。首先,$_SERVER['SCRIPT_NAME'] 和 $_SERVER['SCRIPT_FILENAME'] 都是脚本名称,只是后者是在执行别名之后。其次,$_SERVER['PHP_SELF'] 不是脚本,而是脚本 + 路径信息。同样,$_SERVER['SCRIPT_NAME'] 是脚本(在别名之前)。最后,了解在哪个阶段,在重写规则之后或之前,在别名之后或之前,定义这些变量是很有用的。看看我的答案。
0赞 Beejor 12/17/2015
@Dominic108 我根据您的建议修改了我的答案,整理了一下,并添加了操作顺序部分。让我知道你的想法。谢谢!
0赞 12/17/2015
在您的订单中,您必须交换 和 ,因为mod_rewrite创建整个路径,即 。接下来发生分离。请注意,别名还会考虑定义脚本文件名的整个路径,但定义 script_name 和 path_info 的分离已经发生,因此它们不会受到影响。$_SERVER['SCRIPT_NAME']$_SERVER['PHP_SELF']$_SERVER['PHP_SELF']
0赞 Beejor 1/18/2016
@Dominic108我再次修改了我的答案。由于某种原因,您的编辑建议被拒绝了,但据我所知,您是正确的,我的两个项目出了问题。我对别名不太熟悉,所以我依靠你的专业知识来完成这部分。 再次感谢!
4赞 user2066805 12/16/2015 #8

奥丁的回答几乎没有什么可补充的。我只是想提供一个完整的示例,从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 

别名影响系统文件路径,而不是 URL 路径,这些路径在之前定义 - 请参阅下面的例外情况。别名可能使用整个 URL 路径,包括 .和 之间可能根本没有联系。SCRIPT_FILENAME__FILE__PATH_INFOSCRIPT_NAMESCRIPT_FILENAME

在定义 URL 路径时未解析别名并不完全准确,因为别名被认为是搜索文件系统的,我们从 Oin 回答中的示例 4 中知道,搜索文件系统以确定文件是否存在,但这仅在未找到文件时才相关。同样,mod_dir调用mod_alias来搜索文件系统,但这仅在您具有别名(例如)且请求 uri 是目录时才相关。[PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO]Alias \index.php \var\www\index.php

评论

0赞 Beejor 12/17/2015
嗨,Dominic108,感谢您的修改。我确实认为包含重写信息很有用。对我来说,这是暗示的,但对其他人来说,它可能没有那么直观。
1赞 AbsoluteƵERØ 7/23/2018 #9

如果你忘记了哪些变量做了什么,你可以编写一个使用 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赞 TechDogLover OR kiaNasirzadeh 5/23/2023 #10

简单易行的简单答案:

假设
之后会有两种可能性:
1-查询字符串,如
2-更多路径信息,如
scheme://host/path/script.phpscript.phpscheme://host/path/script.php?qs=ascheme://host/path/script.php/more/path


现在我们有一个非常简单的规则:

财产 包括什么 例如:http://localhost/dashboard/paln5/st1.php/a/b?c=d
REQUEST_URI 之后的所有内容都包括在内 /dashboard/paln5/st1.php/a/b?c=d
PHP_SELF 只是包含更多路径 /dashboard/paln5/st1.php/a/b
SCRIPT_NAME 之后不包含任何内容 /dashboard/paln5/st1.php