PHP_SELF与PATH_INFO对比SCRIPT_NAME与REQUEST_URI

我正在CodeIgniter中构build一个PHP应用程序。 CodeIgniter发送所有请求到主控制器: index.php 。 但是,我不喜欢在URI中看到index.php 。 例如, 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等得到它,但我正在试图决定哪一个最可靠。 有谁知道(或知道在哪里可以find) PHP_SELFPATH_INFOSCRIPT_NAMEREQUEST_URI之间的真正区别吗? 谢谢你的帮助!

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

更新 :修复了空格。

PHP文档可以告诉你不同之处:

'PHP_SELF'

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

'SCRIPT_NAME'

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

'REQUEST_URI'

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

PATH_INFO似乎没有logging…

这些variables之间差异的一些实际例子:
示例1. PHP_SELF 在请求的URL在表单中时与SCRIPT_NAME不同:
http://example.com/test.php/foo/bar

 [PHP_SELF] => /test.php/foo/bar [SCRIPT_NAME] => /test.php 

(这似乎是唯一的情况下,当PATH_INFO包含明智的信息[PATH_INFO] => /富/酒吧)注意:这在一些旧的PHP版本(<= 5.0?)是不同的。

示例2.input非空查询string时,REQUEST_URI与SCRIPT_NAME不同:
http://example.com/test.php?foo=bar

 [SCRIPT_NAME] => /test.php [REQUEST_URI] => /test.php?foo=bar 

例3.当服务器端的redirecton生效时,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 

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

path

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

path

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 ^(([az]{2})|(([az]{2})/)?(.*))$ index.php/$5 [NC,L,E=LANGUAGE:$2$4] 

要么

 RewriteRule ^([az]{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 

path

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 

语言path

http://domain.com/en/test

 [PHP_SELF] => /index.php/test [PATH_INFO] => /test [REQUEST_URI] => /en/test [REDIRECT_LANGUAGE] => en 

语言查询string

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 

PHPpath

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

哪里

  • 文件path是一个系统文件path,/var/www/index.php ,别名parsing后
  • Webpath是一个服务器文档path,http://foo.com/index.php /index.php ,甚至可能不匹配任何文件
  • 当前文件意味着包含的脚本文件 ,而不是包含它的任何脚本
  • 请求的文件意味着includer脚本文件 ,而不是包含的文件
  • 在任何URL重写之前, URI都是/index.php?foo=bar这样的HTTP请求
  • path信息是位于脚本名称之后但位于查询string之前的任何额外的Apache数据

操作顺序

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

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

返回一个完整URI的string。

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

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

该函数将返回这个:

 /news/local/345 

或者,您可以利用这些细分来深入了解特定区域,而不必提出parsing/正则expression式值

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

奥丁的答案几乎没有增加。 我只是想从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 

Apacheconfiguration文件包含别名

 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重写或任何forms的URL重写,我们也有

 REQUEST_URI = PHP_SELF + ? + QUERY_STRING 

别名影响系统文件pathSCRIPT_FILENAME__FILE__ ,而不是之前定义的URLpath – 请参阅下面的例外。 别名可能会使用整个URLpath,包括PATH_INFOSCRIPT_NAMESCRIPT_FILENAME之间根本没有连接。

在定义URLpath[PHP_SELF] = [SCRIPT_NAME] + [PATH_INFO] ,别名不能被parsing,因为别名被认为是search文件系统,我们从Odin的答案的例子4中知道文件系统被search以确定文件是否存在,但是这只在找不到该文件时才有意义。 类似地,mod_dir调用mod_alias来search文件系统,但是这只有在别名(如Alias \index.php \var\www\index.php和请求URI是一个目录时才有意义。

备份第二个,你已经采取了错误的做法开始。 为什么不这样做呢

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

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