使用PHP模拟“假”目录,不使用.htaccess,mod_rewrite或404重定向

时间:2013-09-20 16:02:02

标签: php redirect nginx subdirectory virtual-directory

情况

您好,我对PHP关于无扩展PHP文件的预期/默认行为以及/或“过去”(我想要)处理请求的实际文件的URL请求感到困惑(即,PHP的默认“回退” “在采取行动之前采取行动完全404-ing”。这是我的情况:

我的本​​地服务器上的目录结构(使用非常基本的PHP 5.5.1设置运行nginx 1.5.3)如下所示:

/index
/index.php
/other
/other.php
/rootdir/index
/rootdir/index.php
/rootdir/other
/rootdir/other.php

所有八个文件的内容都是相同的:

<?php
echo $_SERVER['PHP_SELF'] . ', ' . $_SERVER['REQUEST_URI'];
?>

但是,点击相应的端点会产生一些奇怪的(对我而言)结果。

研究

GET /index.php
'/index.php, /index.php' # Makes sense...

GET /index.php/something_else
'/index.php, /index.php/something_else' # Also makes sense...

GET /index/something_else
'/index.php, /index/something_else' # Let's call this ANOMALY 1... (see below)

GET /something_else
'/index.php, /something_else' # ANOMALY 2

GET /other.php
'/other.php, /other.php' # Expected...

GET /other.php/something_else
'/index.php, /other.php/something_else' # ANOMALY 3

GET /rootdir/index.php
'/rootdir/index.php, /rootdir/index.php' # Expected...

GET /rootdir/index.php/something_else
'/index.php, /rootdir/index.php/something_else' # ANOMALY 4

GET /rootdir/other.php
'/rootdir/other.php, /rootdir/other.php' # Expected...

GET /rootdir/other.php/something_else
'/index.php, /rootdir/other.php/something_else' # ANOMALY 5

我的理解是当服务器无法在请求URI中找到用户正在查找的内容时,服务器会重定向到/index.php;那很有意义...... 我不明白是:

  1. 为什么它会这样做尽管我没有设置专用的404页面(我没有告诉它在404-ing之前尝试/index.php;我想要< / em>它显示一个合法的,非自定义的404页面,如果找不到和/或无法处理。我认为它应该显示默认服务器404页面,当它找不到的东西......显然情况并非总是如此......?)
  2. 为什么它在/rootdir/index.php子目录中找不到内容时不会尝试/rootdir/
  3. 问题

    1. 对于未找到的地址,是否有人能够阐明PHP的逻辑是什么(或者可能是nginx正在做的事情;我还未能解决这个问题)?为什么我看到我所看到的? (特别是关于异常#4和#5。我希望它使用/rootdir/index.php来处理它的“404”, 我期待一个真正的404页面; /index.php的回退是出乎意料的。)

    2. 作为直接推论(corollical?)的问题,如何模拟无扩展的PHP文件来处理“低于”它们的命中(例如在Anomaly#1案例中) ;这实际上正是我想要的,虽然它不是我想象的那样 没有 依赖.htaccess,mod_rewriting或重定向?或者这是一个愚蠢的问题? : - )

    3. 参考

      我正在尝试推出一个自定义实现来处理/some_dir/index.php/fake_subdir/some_other_dir/index.php/fake_subdir等请求(即不同的“回退处理程序”),而不依赖于Apache,但是PHP(或nginx)背后的逻辑?)默认回退行为是逃避我。这些页面主要来自这个问题:

2 个答案:

答案 0 :(得分:1)

 GET /other.php/something_else

这在Apache中称为PATH_INFO。当Apache扫描URL的“目录”时,它将返回第一个文件(或执行第一个脚本),实际上是文件/脚本,例如。

GET /foo/bar/baz/index.php/a/b/c/
     ^--dir
         ^--dir
             ^---dir
                 ^---script
                         ^^^^^^^--- path_info

实际上,真正的要求是

GET /foo/bar/baz/index.php

然后Apache将获取URL的目录结构的未使用的尾部,并将其转换为路径信息。在PHP中,你将有

$_SERVER['REQUEST_URI'] = '/foo/bar/baz/index.php';
$_SERVER['PATH_INFO'] = 'a/b/c';

答案 1 :(得分:0)

好吧,我弄清楚发生了什么:我的配置错误的nginx服务器。

Marc B的回答虽然与Apache有关,但却促使我查看了我的PATH_INFO值 - 看, PATH_INFO不存在,,即使对GET /other.php/something_else这样的请求也是如此。

更多的搜索结果显示了答案。使用nginx的fastcgi_split_path_info将URI拆分为a)脚本的路径和b)脚本名称后面显示的路径失败如果在之后 使用try_files指令,因为它重写URI 指向磁盘上的文件。这消除了获取PATH_INFO字符串的任何可能性。

作为一个解决方案,我做了三件事(其中一些可能是多余的,但我做了所有这些,以防万一):

  1. 在服务器的位置区块中,在 之前使用fastcgi_split_path_info

    通过

    设置PATH_INFO
    fastcgi_param PATH_INFO $fastcgi_path_info;
    

    ...并在 之前

  2. try_files存储为本地变量,以防以后更改(例如使用$fastcgi_path_info

  3. 使用set $path_info $fastcgi_path_info;时,使用try_files ...使用$uri。 (很确定这是我最大的错误。)

  4. 样本配置

    $fastcgi_script_name

    server { # ... *snip* ... location ~ \.php { # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_index index.php; fastcgi_intercept_errors on; fastcgi_pass 127.0.0.1:9000; try_files $fastcgi_script_name =404; } # ... *snip* ... } 包含的位置:

    fastcgi_params

    参考

    以下链接可以很好地解释问题并提供备用nginx配置: