PSR-0 自动加载器问题

PSR-0 autoloader issue

我在 PSR-0 自动加载项目中按路径实例化 class 时遇到问题。结构如下:

| - src/
|    - Models/
|        - My_New_Model_Migration.php
|        - ...
|    SeederCommand.php
| - vendor/
|     - ...
| composer.json

和 Composer 自动加载器:

"autoload": {
    "psr-0": {
        "" : [
            "src/"
        ]
    }
}

SeederCommand class 中不会涉及太多,它基本上是一个 Doctrine/migrations class,它应该使用 up()down() 方法。

在负责生成这些函数的函数中,我有这部分:

if (file_exists(__DIR__ . "/Models/{$model}_Migration.php")) {
    $class = "{$model}_Migration";
    $instantiated = new $class;
    ....
}

回显时我注意到文件确实存在,所以这部分工作正常。但是,更新 class 时出现错误:

PHP Fatal error: Uncaught Error: Class '/var/www/html/.../src/Models/My_New_Model_Migration.php' not found in /var/www/html/.../src/SeederCommand.php:97

由于路径是正确的,我认为问题一定出在 PSR-0 自动加载器通过下划线解析路径的方式工作?

有什么解决办法吗?

编辑:

This answer 对我没有帮助,因为它解释了自动加载器故事的 'why'。我知道 PSR-0PSR-4 自动加载器是如何在高层次上工作的。我想解决自动加载器需要一个包含 none 的目录结构这一事实(我不希望在这种情况下引入它)。

编辑2:

SeederCommand class 需要自动加载文件:

require "../vendor/autoload.php"; 

我试过 dump-autoload 并将 class 重命名为不带下划线的名称,同样的事情发生了,所以我可能在自动加载本身上做错了。

编辑3:

我尝试更新 class 我重命名为非下划线版本。例如,更新 MyNewClass 有效,但 My_New_Class 会引发错误。

创建新实例时出错 class

$class = __DIR__ . "/Models/{$model}_Migration.php";
$instantiated = new $class;

这是错误的,因为您不能通过其文件名创建 class 的实例,例如:

$instance = new /var/www/html/.../Class.php; // <-- wrong

您需要使用 class 名称和命名空间:

$instance = new \Project\Namespace\Class;

因此在您的特定情况下,它可能类似于

$class = "\Project\Models\".$model."_Migration";
// ^ depends on the real namespace and name of your migration classes
$instantiated = new $class;

PSR-0 和下划线

再次阅读 PSR-0 Standard 后,老实说,我认为在使用 PSR-0 时无法实现您想要的(具有带下划线但没有目录的 class 名称)。该标准明确指出:

Each _ character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR.

可能的解决方案:类图自动加载器

但您可以对这些文件使用 composer's classmap autoloader

This map is built by scanning for classes in all .php and .inc files in the given directories/files. You can use the classmap generation support to define autoloading for all libraries that do not follow PSR-0/4. To configure this you specify all directories or files to search for classes.

它可能看起来像那样(但我无法测试):

"autoload": {
    "psr-0": {
        "" : [
            "src/"
        ]
    },
    "classmap": ["src/Models/"]
}

您的 class 名称中不能有下划线,目录结构中也不能有下划线。

如果您的 class 被命名为 Models_MyWhatever_Migration,因为您在迁移期间将字符串 "MyWhatever" 动态添加到 class 名称,那么 class 必须是置于 src/Models/MyWhatever/Migration.php。你不能在 src/Models/MyWhatever_Migration.php.

中使用它

如果你想保留下划线作为文件名的一部分,你必须切换到 PSR-4 并使用命名空间。