PHP_SELF,PATH_INFO,SCRIPT_NAME,REQUEST_URI


105

我正在CodeIgniter中构建一个PHP应用程序。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_URIPATH_INFO等获得它,但是我正在尝试确定哪一个最可靠。没有人知道(或不知道在哪里可以找到)之间的真正区别PHP_SELFPATH_INFOSCRIPT_NAME,和REQUEST_URI?谢谢你的帮助!

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

更新:修复了空格。

Answers:


51

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似乎没有记录在案...


3
这很可能与PHP文档无关,而与CGI有关:)并记录了PATH_INFO:tools.ietf.org/html/rfc3875#section-4但是有一些已知问题,Apache和nginx并不总是提供此变量。
SimonSimCity

1
奥丁(Odin)在下面的回答中添加了有用的解释,并辅以示例。我发现很难理解这些变量在一般上下文中用path_info,查询字符串,某些重定向,某些别名(在不同操作系统上,从CLI到SERVER等

3
-1就像对我为什么投票的解释:我来这篇文章的全部原因是因为文档不清晰。奥丁(Odin)在下面的回答清楚地解释了这些变量之间的区别。我觉得仅复制和粘贴容易找到的文档还是不够的答案是不够的。我相信大多数人都必须已经访问过该文档才能了解上述$ _SERVER变量中的元素列表。
达林

229

关于这些变量之间差异的一些实际示例:
示例1. 当请求的URL的格式为:http//example.com/test.php/foo/bar时,PHP_SELF与SCRIPT_NAME 不同

[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

21
+1,“一个例子不是学习的方法,而是学习的唯一方法。” -我总是必须重新检查这些内容,对404错误进行非常好的研究。=)
Alix Axel,2010年

16
+1:我一生中第一次了解这种差异。他们应该使用您的答案来更新PHP documentaion
Marco Demaio 2011年

Example1:[SCRIPT_NAME] => /test.php/结尾不应该包含“ /”:Example1:[SCRIPT_NAME] => /test.php无论如何,这是我在PHP 5.3.6中看到的。很好的例子。
戴维德·欧亚

您是正确的JohnM2,我现在检查过PHP 5.4,URL /pinfo.php/first/second?third=fourth的结果如下:QUERY_STRING => third = fourth REQUEST_URI => /pinfo.php/first/second ?third =第四SCRIPT_NAME => /pinfo.php PATH_INFO => / first / second
Odin

我也在5.2.17上进行了测试/,末尾没有内容SCRIPT_NAME。然后,考虑编辑答案以反映这一点,这在PHP 5.2-5.4中似乎是一致的。
FABRICIO磨砂

24

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

太好了 谢谢你的帮助!
加百利博览会

1
该答案的编写方式表明只有url重写才能创建path_info,但是当然可以直接在原始URL中输入路径信息。

12

PHP路径

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

哪里

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

操作顺序

  1. 客户端向服务器发送HTTP请求 REQUEST_URI
  2. 服务器从.htaccess文件等执行任何URL重写以获取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']是脚本(在别名之前)。最后,知道在什么时候,在重写规则之后或之前,在别名之后或之前定义这些变量是很有用的。看我的答案。

@ Dominic108我根据您的建议修改了答案,整理了一些内容,并添加了“操作顺序”部分。让我知道你的想法。谢谢!
Beejor

在您的订单中,您必须交换$_SERVER['SCRIPT_NAME']和   $_SERVER['PHP_SELF'],因为mod_rewrite创建了整个路径,即$_SERVER['PHP_SELF']。接下来发生分离。请注意,别名还考虑了用于定义脚本文件名的整个路径,但是定义script_name和path_info的分隔已经发生,因此它们不会受到影响。

@ Dominic108我再次修改了答案。由于某种原因,您的编辑建议被拒绝了,尽管据我所知,您是正确的,我的两个项目已损坏。我对别名不那么熟悉,所以我依赖您的专业知识。再次感谢!
Beejor

5

您可能需要研究URI类,并使用$ this-> uri-> uri_string()

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

例如,如果这是您的完整URL:

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

该函数将返回以下内容:

/news/local/345

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


谢谢-这是个好主意,但是我在控制器启动和运行之前需要先运行它们的系统前挂钩中使用它们。
伊莱

4

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


它总是完整的URI吗?
伊莱

通常,您可能会在Windows上遇到Apache问题,但这仅适用于无法解决的URI。
Xenph Yan

4

奥丁的答案几乎没有增加。我只是想提供一个从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路径,这是以前定义-见下文例外。别名可能会使用整个网址路径,包括PATH_INFOSCRIPT_NAME和之间可能根本没有连接SCRIPT_FILENAME

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


您好Dominic108,感谢您的修改。我确实认为包含重写信息很有用。对我而言,这是隐含的,但对其他人而言,可能不是那么直观。
Beejor

1

如果您忘记了哪个变量在做什么,则可以编写一个使用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


-1

备份一秒钟,您就采用了错误的方法。为什么不这样做

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

代替?然后用$_GET['url'];


为什么要重新发明轮子?此数据更容易访问!
肯尼斯(Kenneth)

如果原始请求中希望包含查询字符串,则还会带来额外的复杂性。在当前状态下,以上代码将简单地覆盖查询字符串。如果合并查询字符串(QSA标志),则查询字符串参数可能会被覆盖(例如,如果您url在初始请求上需要一个参数),甚至更糟,这很容易受到XSS攻击。
怀特先生'17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.