在PHP中,自动加载文件时,PHP会在哪里寻找这些文件?

In PHP, when autoloading files, where PHP will look for these files?

我有一个基于 MVC 的应用程序,它具有基本的 URL 重写规则,这使得 URL 看起来像这样:website/controller/action/idid 是可选的。

如果用户输入无效的 action,他应该得到一个错误,该错误在 class ErrorController.

中处理

我的所有 classes 文件在 autoloader 文件中都是必需的,所以我不应该在每次创建对象时都需要它们。我使用 spl_autoload_register() 进行自动加载。

当我尝试输入带有无效 action 的 URL 时出现问题。例如,对于 URL website/main/inde(而不是 index)- 应该创建 ErrorController 的实例。

相反,我得到了这两个 PHP 错误:

Warning: require(!core/errorcontroller.php): failed to open stream: No such file or directory in D:\Programs\Wamp\www\fanfics\v0.0.2!core\autoloader.php on line 5

Fatal error: require(): Failed opening required '!core/errorcontroller.php' (include_path='.;C:\php\pear') in D:\Programs\Wamp\www\fanfics\v0.0.2!core\autoloader.php on line 5

这是我的文件的视图(core 文件夹前的感叹号是为了将其放在顶部):

index.php:

<?php

require "!core/autoloader.php";

$loader = new Loader();

!core/autoloader.php

<?php

function autoload_core_classes($class)
{
    require "!core/" . strtolower($class) . ".php";
}

function autoload_controllers($class)
{
    require "controllers/" . str_replace("controller", "", strtolower($class)) . ".php";
}

function autoload_models($class)
{
    require "models/" . str_replace("model", "", strtolower($class)) . ".php";
}

spl_autoload_register("autoload_core_classes");
spl_autoload_register("autoload_controllers");
spl_autoload_register("autoload_models");

!core/basecontroller.php

<?php

abstract class BaseController
{

    protected $model;
    protected $view;
    private $action;

    public function __construct($action)
    {
        $this->action = $action;
        $this->view = new View(get_class($this), $action);
    }

    public function executeAction()
    {
        if (method_exists($this->model, $this->action))
        {
            $this->view->output($this->model->{$this->action}());
        }
        else
        {
            // Here I create an ErrorController object when the action is invalid
            $error = new ErrorController("badmodel");
            $error->executeAction();
        }
    }
}

如果我尝试特别要求 controllers/error.php - 它工作得很好:

.
.
.
else
{
    require "controllers/error.php"; // With this line it works just fine
    $error = new ErrorController("badmodel");
    $error->executeAction();
}

网上找了好久,才知道可能是include_path有问题,但不是很明白。我该如何解决这个问题?

每个自动加载器函数最好在盲目尝试 include/require 之前检查文件是否存在。自动加载器不应抛出任何错误并且应该静默失败,以便它们可以允许队列中的下一个自动加载器尝试自动加载必要的文件。

<?php

function autoload_core_classes($class)
{
    if (is_readable("!core/" . strtolower($class) . ".php"))
        include "!core/" . strtolower($class) . ".php";
}

function autoload_controllers($class)
{
    if (is_readable("controllers/" . str_replace("controller", "", strtolower($class)) . ".php"))
        include "controllers/" . str_replace("controller", "", strtolower($class)) . ".php";
}

function autoload_models($class)
{
     if (is_readable( "models/" . str_replace("model", "", strtolower($class)))
        include "models/" . str_replace("model", "", strtolower($class)) . ".php";
}

spl_autoload_register("autoload_core_classes");
spl_autoload_register("autoload_controllers");
spl_autoload_register("autoload_models");

PHP 在 属性 include_path 中定义的路径中搜索包含。对于命令行,您可以使用以下命令检查其值:

php -i | grep include_path

对于网络检查:

phpinfo()

在任何情况下,您都可以修改 php.ini 内的值。

我曾经在我的单一入口点的项目根目录中 chdir(),然后包含具有来自根目录的相对路径的文件。这是有效的,因为 include_path 通常包含当前目录“.”