PHP内置Web服务器和相对路径

4

简而言之

PHP 5.4内置的Web服务器对于相对路径有任何错误或限制吗?还是需要适当(并且另外)配置?


当我以前积极地进行编程时,我在.htaccess文件中使用这些行来处理URI路由:

RewriteEngine On

RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php [L]

前置控制器接收请求,从 SQLITE 数据库中查找给定 URI 的适当路由,并由调度程序调用操作控制器。

在 Apache 下它工作得非常好。今天,几个月后,我决定使用 PHP 5.4 内置 Web 服务器运行我的测试应用程序。

我首先注意到的是,显然 .htaccess 不起作用,所以我使用代码文件代替:

<?php

if( preg_match( '/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"] ) ) {
    return false;
}

include __DIR__ . '/index.php';

我这样启动了Web服务器:

php.exe -c "php.ini" -S "localhost:8080" "path\to\testfolder\routing.php"

到目前为止,一切都很顺利。我的应用程序需要引导的所有内容都可以通过修改include_path来实现,就像这样:

set_include_path(

    '.' . PATH_SEPARATOR . realpath( '../common/next' )
);

在所有应用程序公共文件夹的核心文件夹中,下一个是所有模块的文件夹,不需要进一步解释。

我曾经见过的所有AutoLoader技术都无法自动加载,因此唯一需要手动引入的类是我的Autoloader。但是,在运行测试应用程序后,我收到了一个错误,因为找不到我的Autoloader。

我一直对realpath()很怀疑,所以我决定将其更改为此next目录的完整绝对路径,然后它就起作用了。虽然不需要像我这样做,但它确实有效。

我的autoloader被成功加载并由spl_autoload_register()注册。供参考,这是autoloading函数(仅包含Closure):

function( $classname ) {

    $classname = stream_resolve_include_path(

        str_replace( '\\', DIRECTORY_SEPARATOR, $classname ) . '.php'
    );

    if( $classname !== FALSE ) {

        include $classname;
    }
};

然而,位于 index.php 路径内的资源,例如MVC类,无法找到。因此,我做了另一件我不应该做的事情,就是将工作目录添加到 include_path 中。同样,手动进行,而不依赖于 realpath():

set_include_path(

    '.' . PATH_SEPARATOR . 'path/to/common/next'
        . PATH_SEPARATOR . 'path/to/htdocs/testfolder/'
);

它再次工作了...几乎! >.<

我可以使用这个系统创建的大部分应用都能够很好地在我基于SQLITE数据库的标准路由器上运行。为了使事情更加简单,该路由器会在工作目录中寻找预定义的SQLITE文件。

当然,我也提供了一种方法来更改这个默认条目,以防万一,因此我检查这个文件是否存在,并在不存在时触发错误。

这就是我看到的特定错误。检查程序如下:

if( ! file_exists( $this -> options -> dbPath ) ) {

    throw RouterException::connectionFailure(

       'Routes Database File %s doesn\'t exist in Data Directory',

       array( $this -> options -> dbPath )
    );
}

如果没有更改,dbPath 条目将使用一个常量值 Data/Routes.sqlite,相对于工作目录。
如果我手动设置绝对路径,则一切都可以(真的)正常工作,并且请求流成功到达操作控制器。
发生了什么?

嗨,这里也遇到了同样的问题(使用 PHP 5.3x)。问题出在 PHP HTTP 服务器上。如果你只用 HTML 应用程序尝试,也会得到同样的问题。 - ZEE
我注意到,如果我在相对路径定义的目录中运行负责启动内置Web服务器的批处理脚本,有时会工作。但这取决于应用程序(例如phpMyAdmin无法工作),这是一个可怕的限制,因为我不能同时运行两个不同的应用程序-或者说两个Web服务器运行应该监听两个不同的端口。更糟糕的是!如果没有这个错误,只需要一个指向“。”的批处理脚本就足够了,但现在我必须拥有几个批处理脚本,每个应用程序一个。 - user753531
1
我不知道有任何配置指令可以更改这个行为。我仍然认为PHP的内部Web服务器缺少内部重定向。我的错误报告被立即标记为“非错误”:https://bugs.php.net/bug.php?id=66191 - Jens A. Koch
1个回答

1
这是PHP内置Web服务器的一个错误,截至PHP 5.6.30版本仍未修复。
简而言之,如果请求了www.foo./bar目录,Web服务器不会重定向到www.foo.com/bar/。客户端将被服务于www.foo.com/bar,因为缺少末尾的斜杠,它会认为它是一个文件,所以所有后续相对链接将相对于www.foo.com/而不是www.foo.com/bar/
2013年曾经提出过一个错误票,但错误地将其设置为“非错误”状态。
我在2017年遇到了类似的问题,所以我在错误票上留下了评论。
编辑:刚刚注意到@jens-a-koch打开了我链接的那张票。我没有意识到他对原始问题的评论。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接