【问题标题】:PHP Built-in Webserver and Relative PathsPHP 内置 Web 服务器和相对路径
【发布时间】:2014-09-25 13:17:55
【问题描述】:

TL;DR

PHP 5.4 内置的网络服务器是否有关于相对路径的错误或限制?还是需要正确(以及额外)配置?


当我过去积极编程时,我有一个系统在 URI 路由下使用 .htaccess 文件中的这些行:

RewriteEngine On

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

FrontController 收到请求,从 SQLITE 数据库中的给定 URI 中找到正确的路由,然后 Dispatcher 调用 Action Controller。

它与 Apache 配合得非常好。几个月后的今天,我决定使用 PHP 5.4 内置网络服务器运行我的测试应用程序。

我注意到的第一件事,显然 .htaccess 不起作用,所以我改用了代码文件:

<?php

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

include __DIR__ . '/index.php';

并像这样启动网络服务器:

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

到目前为止,一切都很好。我的应用程序需要引导的一切都可以通过修改 include_path 来完成,如下所示:

set_include_path(

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

成为next文件夹内所有模块的core文件夹,其中包含我拥有的所有应用程序共有的所有内容。并且不需要为此做任何进一步的解释。

我所见过的AutoLoader技术都不能自己autoload,所以唯一需要手动的类就是我的Autoloader。但是在运行测试应用程序后,我收到一个错误,因为找不到我的 AutoLoader。 o.O

我一直对 realpath() 非常怀疑,所以我决定用这个 next 目录的完整和绝对路径来更改它,并且它起作用了。不需要像我那样做,但它确实有效。

我的自动加载器已被 spl_autoload_register() 加载并成功注册。作为参考,这是 autoloading 函数(当然只有闭包):

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

如果我再次手动设置绝对路径,一切(真的)工作正常,请求流成功到达动作控制器。

发生了什么事?

【问题讨论】:

  • Yop.. 同样的问题...(使用 php 5.3x)...问题出在 PHP HTTP 服务器上...如果您仅使用 HTML 应用程序尝试此操作,您会得到同样的问题...
  • 我注意到,如果我从这个相对路径定义所在的目录中运行负责启动内置网络服务器的批处理脚本,它有时会起作用。有时因为取决于应用程序(phpMyAdmin 不起作用)。但这是一个可怕的限制,因为我不能同时运行两个不同的应用程序 - 或者 - 两个网络服务器运行都应该监听两个不同的端口。更差!我会有几个批处理脚本,每个应用程序一个,如果没有这个错误,只有一个指向“。”就够了。
  • 我不知道有任何配置指令可以更改此行为。我仍然认为 PHP 的内部网络服务器错过了内部重定向。我的错误报告立即被标记为不是错误bugs.php.net/bug.php?id=66191

标签: webserver relative-path php-5.4


【解决方案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/获取。

A bug ticket was opened 早在 2013 年,但被错误地设置为“不是错误”状态。

我在 2017 年遇到了类似的问题,所以我在 bug 票上留下了评论。

编辑:刚刚注意到@jens-a-koch 打开了我链接的票证。我不知道他对原始问题的评论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-29
    • 2016-11-05
    • 1970-01-01
    • 2016-12-25
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多