模拟;假;使用PHP的目录,没有.htaccess、mod_rewrite或404重定向 处境

模拟;假;使用PHP的目录,没有.htaccess、mod_rewrite或404重定向 处境,php,redirect,nginx,subdirectory,virtual-directory,Php,Redirect,Nginx,Subdirectory,Virtual Directory,您好,我对PHP在无扩展PHP文件和/或URL请求方面的预期/默认行为感到困惑,这些请求“超过”了(我想)处理请求的实际文件(即,在完全404调用之前,PHP的默认“回退”动作)。我的情况如下: 我的本地服务器上的目录结构(使用非常基本的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文件和/或URL请求方面的预期/默认行为感到困惑,这些请求“超过”了(我想)处理请求的实际文件(即,在完全404调用之前,PHP的默认“回退”动作)。我的情况如下:

我的本地服务器上的目录结构(使用非常基本的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'];
?>
我的理解是,当服务器无法在请求URI中找到用户正在查找的内容时,它会重定向到
/index.php
;这很有道理我不明白的是:

  • 为什么它会这样做,尽管我没有一个专门的404页设置(我没有告诉它在404启动之前尝试
    /index.php
    ;如果找不到和/或无法处理某个内容,我希望它显示一个合法的非自定义404页面。我想当它找不到某个内容时,它应该显示默认的服务器404页面……显然情况并非总是如此……?)
  • 为什么在
    /rootdir/
    子目录中找不到内容时不尝试
    /rootdir/index.php
  • 问题
  • 有人能解释一下PHP对于未找到的地址的逻辑是什么(或者可能是nginx在做什么;我还没弄清楚)吗?为什么我看到了我看到的?(特别是关于异常#4和#5。我希望它使用
    /rootdir/index.PHP
    来处理它的“404,”我期望一个真正的404页面;意外地返回到
    /index.php

  • 作为一个直接的推论(corollic?)问题,我如何去模拟无扩展的PHP文件来处理“在”它们下面发生的点击(例如,在异常情况下,这正是我想要的,尽管它不是我所期望的)而不依赖
    .htaccess
    、修改或重定向?还是一个愚蠢的问题?:-)

  • 工具书类 我正在尝试推出一个定制的实现来处理请求,比如
    /some_dir/index.php/fake_subdir
    /some_other_dir/index.php/fake_subdir
    (即不同的“回退处理程序”),而不依赖Apache,但php(或nginx)背后的逻辑是什么我无法理解默认的回退行为。这些页面主要是这个问题的来源:

    这在Apache中称为
    PATH\u 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目录结构中未使用的尾随部分转换为路径信息

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

    好吧,我弄明白发生了什么:我有一个配置错误的nginx服务器

    Marc B的回答虽然与Apache有关,但却促使我检查我的路径信息值——瞧,路径信息根本不存在,即使对于像
    GET/other.php/something\u other
    这样的请求也是如此

    更多的搜索找到了答案。使用nginx的
    fastcgi\u split\u path\u info
    将URI拆分为a)脚本路径和b)脚本名称后面出现的路径将失败,如果在使用
    try\u files
    指令后执行,因为它会重写URI以指向磁盘上的文件。This消除了获取路径信息字符串的任何可能性

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

  • 在服务器的位置块中,在通过设置路径信息之前,使用
    fastcgi\u split\u path\u info

    fastcgi_param PATH_INFO $fastcgi_path_info;
    
    …并在使用
    try_文件之前执行

  • $fastcgi\u path\u info
    存储为局部变量,以防以后发生更改(例如,使用
    设置$path\u info$fastcgi\u path\u info;

  • 当使用
    try_文件时,不要使用
    $uri
    …使用
    $fastcgi_script_name
    (这肯定是我最大的错误。)

  • 示例配置 其中,
    fastcgi_参数
    包含:

    set            $path_info         $fastcgi_path_info;
    fastcgi_param  PATH_INFO          $path_info;
    fastcgi_param  PATH_TRANSLATED    $document_root$path_info;
    
    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    
    # ... *snip* ...
    
    参考文献 以下链接很好地解释了该问题,并提供了另一种nginx配置:


    感谢您对Apache正常运行方式的澄清。这为我指明了正确的方向,说明了为什么我的主机(使用Apache)和本地服务器(使用nginx)的运行方式不同。不幸的是,我没有使用Apache进行开发(测试除外),这并没有解决我无法访问像
    /foo/bar/baz/index.php/a/b/c/
    这样的URL的问题,而是让
    /foo/bar/baz/index.php
    处理请求:在我的情况下,
    /index.php
    会得到控制。我想我已经解决了这个问题,并发布了一个可能的解决方案——更多细节请参阅我的帖子。
    fastcgi_param PATH_INFO $fastcgi_path_info;
    
    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* ...
    
    }
    
    set            $path_info         $fastcgi_path_info;
    fastcgi_param  PATH_INFO          $path_info;
    fastcgi_param  PATH_TRANSLATED    $document_root$path_info;
    
    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    
    # ... *snip* ...