IIS环境,获取$_SERVER[‘REQUEST_URI’]的问题,REQUEST_URI

IIS环境下正确获取$_SERVER[‘REQUEST_URI’]的问题

这个问题困扰了很久  分页$page失效就是因为它

本地测试是apache 

服务器上是IIS6.0 于是悲剧就这么产生了
下面附上 解决方法:
众所周知,$_SERVER[‘REQUEST_URI’]非常好用,但仅限于Apache环境下,那么要在IIS环境下获取这个参数该怎么办呢?

第一种办法是通过配置环境解决,这个方法不敢确定,因为不知道如何配置的,但之前见过某些特殊配置过的IIS环境是可以获取到$_SERVER[‘REQUEST_URI’]参数的。

第二种办法当然就是通过程序解决了,程序代码如下:
 
// Fix for IIS, which doesn’t set REQUEST_URI
if ( empty( $_SERVER[‘REQUEST_URI’] ) ) {
    // IIS Mod-Rewrite
    if (isset($_SERVER[‘HTTP_X_ORIGINAL_URL’])) {
        $_SERVER[‘REQUEST_URI’] = $_SERVER[‘HTTP_X_ORIGINAL_URL’];
    }
    // IIS Isapi_Rewrite
    else if (isset($_SERVER[‘HTTP_X_REWRITE_URL’])) {
        $_SERVER[‘REQUEST_URI’] = $_SERVER[‘HTTP_X_REWRITE_URL’];
    } else {
        // Use ORIG_PATH_INFO if there is no PATH_INFO
        if ( !isset($_SERVER[‘PATH_INFO’]) && isset($_SERVER[‘ORIG_PATH_INFO’]) )
            $_SERVER[‘PATH_INFO’] = $_SERVER[‘ORIG_PATH_INFO’];
        // Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
        if ( isset($_SERVER[‘PATH_INFO’]) ) {
            if ( $_SERVER[‘PATH_INFO’] == $_SERVER[‘SCRIPT_NAME’] )
                $_SERVER[‘REQUEST_URI’] = $_SERVER[‘PATH_INFO’];
            else
                $_SERVER[‘REQUEST_URI’] = $_SERVER[‘SCRIPT_NAME’] . $_SERVER[‘PATH_INFO’];
        }
        // Append the query string if it exists and isn’t null
        if (isset($_SERVER[‘QUERY_STRING’]) && !empty($_SERVER[‘QUERY_STRING’])) {
            $_SERVER[‘REQUEST_URI’] .= ‘?’ . $_SERVER[‘QUERY_STRING’];
        }
    }
}
 把这段代码放在获取$_SERVER[‘REQUEST_URI’]的语句之前就OK了。

==================

if (!isset($_SERVER[‘REQUEST_URI’]))
{
       $_SERVER[‘REQUEST_URI’] = substr($_SERVER[‘PHP_SELF’],1 );
       if (isset($_SERVER[‘QUERY_STRING’])) { $_SERVER[‘REQUEST_URI’].=’?’.$_SERVER[‘QUERY_STRING’]; }
}

changed line 3 to

$_SERVER[‘REQUEST_URI’] = substr($_SERVER[‘PHP_SELF’],0 );

===========

/* 解决 iis 不支持 $_SERVER[‘REQUEST_URI’] */
request_uri();
function request_uri(){ 
if (isset($_SERVER[‘REQUEST_URI’])) 

$uri = $_SERVER[‘REQUEST_URI’]; 

else

if (isset($_SERVER[‘argv’])) 

$uri = $_SERVER[‘PHP_SELF’] .(empty($_SERVER[‘argv’])?”:(‘?’. $_SERVER[‘argv’][0])); 

else

$uri = $_SERVER[‘PHP_SELF’] .(empty($_SERVER[‘QUERY_STRING’])?”:(‘?’. $_SERVER[‘QUERY_STRING’])); 


$_SERVER[‘REQUEST_URI’] = $uri; 
}

==============

<?php
echo request_uri();
function request_uri(){
if (isset($_SERVER[‘argv’]))
{
$uri = $_SERVER[‘PHP_SELF’] .(empty($_SERVER[‘argv’])?”:(‘?’. $_SERVER[‘argv’][0]));
}
else
{
$uri = $_SERVER[‘PHP_SELF’] .(empty($_SERVER[‘QUERY_STRING’])?”:(‘?’. $_SERVER[‘QUERY_STRING’]));

}
return $_SERVER[‘REQUEST_URI’] = $uri;
}
?>

===========

if (!isset($_SERVER[‘REQUEST_URI’])) {
$_SERVER[‘REQUEST_URI’] = substr($_SERVER[‘PHP_SELF’],1 );
if (isset($_SERVER[‘QUERY_STRING’]) AND $_SERVER[‘QUERY_STRING’] != “”) {
$_SERVER[‘REQUEST_URI’] .= ‘?’.$_SERVER[‘QUERY_STRING’];
}
}

===============

经测试在 iis 7.5 中无法使用 $_SERVER[‘REQUEST_URI’] 获得 当前链接地址
 以下是我的解决方法:
show() 方法 修改代码:
 原来的是 
$url = $_SERVER[‘REQUEST_URI’].(strpos($_SERVER[‘REQUEST_URI’],’?’)?”:”?”).$this->parameter;
现改为
$url = $_SERVER[‘SCRIPT_NAME’].’?’.$_SERVER[‘QUERY_STRING’].$this->parameter;
优点:iis 7.5 apache nginx 都可以正常使用了
 缺点:rewrite 或 pathinfo 不支持。
不过官方原来的做法,也不能支持 rewrite 和 pathinfo 官方给解决下吧 

================

获取 _SERVER[‘REQUEST_URI’] 值的通用解决方案

<?php
// 说明:获取 _SERVER[‘REQUEST_URI’] 值的通用解决方案
//isset() #用来测试变量是否被设置。
//$_SERVER[’REQUEST_URI’] #访问此页面所需的 URI。例如,“/index.html”。
//$_SERVER[’argv’] #传递给该脚本的参数。
//$_SERVER[’PHP_SELF’] #当前正在执行脚本的文件名,与 document root相关。
//$_SERVER[’QUERY_STRING’] #查询(query)的字符串。
function request_uri()
{
    if (isset($_SERVER[‘REQUEST_URI’])) 
    {
        $uri = $_SERVER[‘REQUEST_URI’];
    } else 
    {
        if (isset($_SERVER[‘argv’])) 
        {
            $uri = $_SERVER[‘PHP_SELF’] . ‘?’ . $_SERVER[‘argv’][0];
        } else 
        {
            $uri = $_SERVER[‘PHP_SELF’] . ‘?’ . $_SERVER[‘QUERY_STRING’];
        }
    }
    return $uri;
}
?>

例:
//parse_url()是将URL解析成有固定键值名称的数组的函数
$ua = parse_url(“http://127.0.0.5/nn6.php/path111?arg=123#anchor”);
print_r($ua);
echo “</br>”.$ua[“path”];
echo “</br>”;
$uri = $_SERVER[‘REQUEST_URI’]; //取得当前URI,即除域名外 后面的完整地址路径
echo $uri;
输出:
Array ( [scheme] => http [host] => 127.0.0.5 [path] => /nn6.php/path111 [query] => arg=123 [fragment] => anchor ) 
/nn6.php/path111
/nn6.php/path111?arg=123

===========================

Apache与IIS,URL重写机制的不同及REQUEST_URI

将网站做好后,上传到IIS服务器上就不行了,搞了好久,才发现其中原因!网站配置情况:
URL_MODE 2,//开启了Rewrite,隐藏了index.php
在Apache上开发的,.htaccess内容与TP手册中的一样,但IIS使用httpd.ini,并且规则不一样IIS对于Rewrite规则
1. 
2. RewriteRule (.*)$ /index\.php\?s=$1 [I]

的解释是,不管什么样的请求URL,都重写到index.php入口文件而Apache与IIS不一样的地方是,对于规则
1. <IfModule mod_rewrite.c>
2. RewriteEngine on
3. RewriteCond %{REQUEST_FILENAME} !-d
4. RewriteCond %{REQUEST_FILENAME} !-f
5. RewriteRule ^(.*)$ index.php?s=/$1 [QSA,PT,L]
6. </IfModule>

它对于请示的路径会做一些判断,当请求URL是一个存在的文件路径时,则不重写向index.php(本人
对于URL REWRITE 中的REGEXP也不是很熟悉,难道APACHE的这行规则中有什么玄机?)所以,使用了URL 重写,
并且规则只有一条”将所有请求转向index.php”,在APACHE下, Public目录仍然可以访问(里面可是CSS,JS和图片啊!),
而到了IIS下则图片,CSS,JS都加载不进行,并且输入/Public/ ,出现的错误是 没有Public这个模块!

解决方法是,IIS的重写规则不能简单的只指向index.php,需要使用正则表达的前瞻功能,排除指定路径,下面是我的网站的httpd.ini文件,
其中,Ask目录为一个问吧系统的路径,BBS是论坛的路径
1. [ISAPI_Rewrite]2. RewriteRule (?!/ask)(?!/bbs)(?!/Public)(?!/Common)(.*)$ /index\.php\?s=$1 [I]

如果还要排除其它目录的话,只要将(?!/目录名)加在前面就行了
另外,IIS对于重写后的REQUEST_URI的解析也与Apache不一样,如果使用了重写,IIS不会将在地址栏中的URL记为REQUEST_URI,而是重写后的URI
如下面的URL
/pro/show/id/1.htm使用重写
1. 
2. RewriteRule (.*)$ /index\.php\?s=$1 [I]

本来是执行Pro模块的show方法,为1,在Pro模块中获取REQUEST_URI,值应为
/pro/show/id/1.htm
但在IIS中是
/index.php?s=/pro/show/id/1.htm 
解决这个问题的方法之前也有了,在国外一个网站上看到的
1. //ISAPI_Rewrite 3.x
2. if (isset($_SERVER[‘HTTP_X_REWRITE_URL’])){
3. $_SERVER[‘REQUEST_URI’] = $_SERVER[‘HTTP_X_REWRITE_URL’];
4. }}
5. //ISAPI_Rewrite 2.x w/ HTTPD.INI configuration
6. else if (isset($_SERVER[‘HTTP_REQUEST_URI’])){
7. $_SERVER[‘REQUEST_URI’] = $_SERVER[‘HTTP_REQUEST_URI’];
8. //Good to go!
9. }
10. //ISAPI_Rewrite isn’t installed or not configured11. else{
12. //Someone didn’t follow the instructions!
13. if(isset($_SERVER[‘SCRIPT_NAME’]))
14. $_SERVER[‘HTTP_REQUEST_URI’] = $_SERVER[‘SCRIPT_NAME’];
15. else
16. $_SERVER[‘HTTP_REQUEST_URI’] = $_SERVER[‘PHP_SELF’];
17. if($_SERVER[‘QUERY_STRING’]){
18. $_SERVER[‘HTTP_REQUEST_URI’] .= ‘?’ . $_SERVER[‘QUERY_STRING’];
19. }
20. //WARNING: This is a workaround!
21. //For guaranteed compatibility, HTTP_REQUEST_URI or HTTP_X_REWRITE_URL *MUST* be defined!
22. //See product documentation for instructions!
23. $_SERVER[‘REQUEST_URI’] = $_SERVER[‘HTTP_REQUEST_URI’];
24. }

上面的代码引入的话,即可解决IIS的REQUEST_URI方法(如果对于THINKPHP,其实上面的URL还有更简单的方法)
1. $_SERVER[‘REQUEST_URI’]=$_GET[‘s’];
2. //直接将QS中的s变量赋值给$_SERVER[‘REQUEST_URI’]就行了

上面已经解决了不少问题,但最后一个问题就是,也是我一直没有解决好的问题对于下面的URL
/pro/branch/air.htm?pclass=gree
在APACHE下面,可以获取到GET变量 pclass的值,并且branch变量的值为air(开启了伪静态),而在IIS下,branch值就不正确了,而pcalss则获取不到了
解决方法只有使用
/pro/branch/branch/air/pclass/gree这类的URL或者自己在程序中重新解析URL

======================

<?php 
// 说明:获取 _SERVER[‘REQUEST_URI’] 值的通用解决方案 
function request_uri() 

if (isset($_SERVER[‘REQUEST_URI’])) 

$uri = $_SERVER[‘REQUEST_URI’]; 

else 

if (isset($_SERVER[‘argv’])) 

$uri = $_SERVER[‘PHP_SELF’] .’?’. $_SERVER[‘argv’][0]; 

else 

$uri = $_SERVER[‘PHP_SELF’] .’?’. $_SERVER[‘QUERY_STRING’]; 


return $uri; 

?> 

==========================

以前在弄一个国外的购物网站的时候,碰到过这个问题,今天在看ecmall的源码的时候,看到他里面有这个处理,就截取过来了,碰到这个问题解决起来很麻烦,尤其是在你用apache测试,而服务器却是window环境的iis的时候.看来ecmall考虑的还是蛮周全的,呵呵!
/*———————以下是PHP在不同版本,不同服务器上的兼容处理———————–*/

/* 在部分IIS上会没有REQUEST_URI变量 */
$query_string = isset($_SERVER[‘argv’][0]) ? $_SERVER[‘argv’][0] : $_SERVER[‘QUERY_STRING’];
if (!isset($_SERVER[‘REQUEST_URI’]))
{
$_SERVER[‘REQUEST_URI’] = PHP_SELF . ‘?’ . $query_string;
}
else
{
if (strpos($_SERVER[‘REQUEST_URI’], ‘?’) === false && $query_string)
{
$_SERVER[‘REQUEST_URI’] .= ‘?’ . $query_string;
}
}

Tags: , ,

  • Digg
  • Del.icio.us
  • StumbleUpon
  • Reddit
  • Twitter
  • RSS

Leave a Reply

You must be logged in to post a comment.

文字链