我正在寻找便携式方式来接收(方便的)$_SERVER['PATH_INFO']
变量。
在阅读一段时间后,事实证明PATH_INFO
来自CGI / 1.1,并且我并不总是出现在所有配置中。
获取该变量的最佳方式(主要是安全方式)是什么 - 除了手动提取之外 (安全问题)。
答案 0 :(得分:11)
好吧,我(几乎)确定不使用$_SERVER
超全球密钥,提供另一种方法来找出PATH_INFO
是不可能的,这就是说lets first list all of the $_SERVER keys我们可能使用:
我们显然需要忽略最后两个。现在我们应该(我不知道这个事实,我只是假设,因为你这么说)过滤你提供的链接中存在的所有密钥(which BTW is offline ATM),这给我们留下了以下的钥匙:
关于您对Anthonys answer的评论:
你现在只是在变量变量。
SCRIPT_FILENAME
是CGI的一部分 规范。如果,它将无法使用PATH_INFO
不可用。至于REQUEST_URI
,它是apache的mod_rewrite 具体。 - LiraNuna
我正在运行 LightTPD / 1.4.20-1(Win32),PHP 5.3.0作为CGI,cgi.fix_pathinfo = 1
和$_SERVER['REQUEST_URI']
非常适合我,我还记得在没有人使用mod_rewrite
的日子里使用相同的变量,所以我诚实的谦虚猜测是你在这一点上是完全错误的。关于SCRIPT_FILENAME
密钥,我无法测试那台ATM。尽管如此,如果我们非常努力地闭上眼睛并相信你是对的,那么我们只留下一个变量:
我并没有在这里做过苛刻(我仍然相信有更多的解决方案),但如果PHP_SELF
是你希望我们合作的唯一关键(假设没有强加于PHP_SELF
本身)只剩下一个解决方案:
function PATH_INFO()
{
if (array_key_exists('PATH_INFO', $_SERVER) === true)
{
return $_SERVER['PATH_INFO'];
}
$whatToUse = basename(__FILE__); // see below
return substr($_SERVER['PHP_SELF'], strpos($_SERVER['PHP_SELF'], $whatToUse) + strlen($whatToUse));
}
此函数应该有效,但是使用 __FILE__
常量可能会出现一些问题,因为它返回声明__FILE__
常量的文件的路径,而不是所请求的路径PHP脚本,这就是为什么$ whatToUse适用于:你可以用'SCRIPT_FILENAME'
替换它,或者如果你真的相信你在说什么,只是使用'.php'
。
您还应该read this regarding why not to use PHP_SELF
。
如果这对您不起作用,我很抱歉,但我还能想到其他任何事情。
编辑 - 为您提供更多内容:
REQUEST_URI
是特定于Apache的?)PHP_SELF
vs PATH_INFO
vs SCRIPT_NAME
vs REQUEST_URI
答案 1 :(得分:2)
我认为这是以其他方式获取“path_info”的技巧:
$path_info = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);
例如,访问以下网址:http://somehost.com/index.php/some/path/here,$path_info
的值为:"/some/path/here"
它适用于在Windows和Linux上运行的各种apache服务器,但我不是100%确定它是否“安全”和“可移植”,但是我不会在“所有”服务器配置中测试它,但是似乎工作......
答案 2 :(得分:1)
function getPathInfo() {
if (isset($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
}
$scriptname = preg_quote($_SERVER["SCRIPT_NAME"], '/');
$pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
return $pathinfo;
}
编辑:没有SCRIPT_NAME,并假设您有DOCUMENT_ROOT(或者可以自己定义/发现它)并假设您有SCRIPT_FILENAME,那么:
function getPathInfo() {
if (isset($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
}
$docroot = preg_quote($_SERVER["DOCUMENT_ROOT"], "/");
$scriptname = preg_replace("/^$docroot/", "", $_SERVER["SCRIPT_FILENAME"]);
$scriptname = preg_quote($scriptname, "/");
$pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
return $pathinfo;
}
还有@ Anthony(评论不够,对不起):使用str_replace()将匹配字符串中的任何位置。它不能保证工作,你只想在开始时匹配它。另外,你的方法只是减少1(通过strrpos)来确定SCRIPT_NAME,只有在脚本位于根目录下时才会起作用,这就是为什么你最好将script_filename与docroot区分开来。
答案 3 :(得分:1)
这取决于“便携式”和“安全”的定义。
让我看看我是否理解:
1)您对CLI不感兴趣:
2)您希望在所有OS + HTTP服务器+ PHP组合中使用PATH_INFO:
嗯... $ _SERVER数组中的PHP_INFO由PHP提供给仅在某些条件下执行的脚本,具体取决于上面提到的软件。它并不总是可用。整个$ _SERVER数组也是如此!
简而言之:“ $ _ SERVER取决于服务器”...所以便携式解决方案无法在$ _SERVER上转发......(仅举几个例子:我们有一个教程在NginX HTTP服务器上设置PHP / CGI $ _SERVER变量,请访问kbeezie.com/view/php-self-path-nginx /)
3)尽管如上所述,值得一提的是,如果我们以某种方式将请求的完整URL 作为字符串提供,则可以通过应用正则表达式从中获取PATH_INFO和其他PHP字符串函数,安全地(也将输入字符串验证为有效的URI)。
所以,只要我们有 URL字符串 ...然后是,我们就有了一种便携且安全的方法来确定它的PATH_INFO。
现在,我们有两个明确且重点突出的实施问题:
在几种可能性中,这是一种可能的方法:
1)凭借您对每个HTTP服务器+ OS + PHP版本组合的深入而全面的了解,检查并尝试从$ _SERVER数组获取URL的每种可能性(验证'PHP_SELF','QUERY_STRING','SCRIPT_FILENAME', 'PATH_TRANSLATED','SCRIPT_NAME','REQUEST_URI','PATH_INFO','ORIG_PATH_INFO','HTTP_HOST','DOCUMENT_ROOT'或其他)
2)如果上一步失败,请让PHP脚本返回一个发送“document.URL”信息的javascript代码。 (可移植性问题转移到客户端。)
This code linked here does this.
这是我对这个问题的拙见和态度。
您怎么看?
答案 4 :(得分:0)
发布前我没有看到评论或链接。根据上面引用的页面提供的CGI派生变量,这里可能会有效:
function getPathInfo() {
if (isset($_SERVER['PATH_INFO'])) {
return $_SERVER['PATH_INFO'];
}
$script_filename = $_SERVER["SCRIPT_FILENAME"];
$script_name_start = strrpos($script_filename, "/");
$script_name = substr($script_filename, $script_name_start);
//With the above you should have the plain file name of script without path
$script_uri = $_SERVER["REQUEST_URI"];
$script_name_length = strlen($script_name);
$path_start = $script_name_length + strpos($script_name, $script_uri);
//You now have the position of where the script name ends in REQUEST_URI
$pathinfo = substr($script_uri, $path_start);
return $pathinfo;
}
答案 5 :(得分:-1)
你可以尝试
$_ENV['PATH_INFO']; or
getenv('PATH_INFO'];