【问题标题】:PSR-0 autoloader issuePSR-0 自动加载器问题
【发布时间】:2019-12-22 11:41:28
【问题描述】:

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

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

还有 Composer 自动加载器:

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

在 SeederCommand 类中不多说,它基本上是一个 Doctrine/migrations 类,它应该使用 up() 和 down() 方法创建迁移。

在负责生成的函数里面我有这部分:

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

回显时,我注意到该文件确实存在,因此这部分正在正常工作。但是在更新课程时出现错误:

PHP 致命错误:未捕获的错误:类 '/var/www/html/.../src/Models/My_New_Model_Migration.php' 未在 /var/www/html/.../src/SeederCommand.php:97

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

有办法解决吗?

编辑:

This answer 对我没有帮助,因为它解释了自动加载器故事的“原因”。我知道PSR-0 和PSR-4 自动装载机在高级别上是如何工作的。我想要一种方法来解决自动加载器想要一个没有目录结构的事实(我不希望在这种情况下引入它)。

EDIT2:

SeederCommand 类需要自动加载文件:

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

我尝试做一个dump-autoload 并将类重命名为一个没有下划线的类,同样的事情发生了,所以我可能在自动加载方面做错了。

EDIT3:

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

【问题讨论】:

  • 我不需要'为什么',我知道自动加载器是如何工作的 :) 如果它存在,我需要解决它

标签: php composer-php psr-0


【解决方案1】:

类名中不能有下划线,目录结构中也不能有下划线。

如果您的类被命名为Models_MyWhatever_Migration,因为您在迁移过程中动态地将字符串“MyWhatever”添加到类名中,所以该类必须放在src/Models/MyWhatever/Migration.php 中。您不能在src/Models/MyWhatever_Migration.php 中拥有它。

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

【讨论】:

    【解决方案2】:

    创建新类实例时出错

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

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

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

    您需要使用类名和命名空间:

    $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 NAME 中的每个 _ 字符都转换为 DIRECTORY_SEPARATOR。

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

    但您可以将composer's classmap autoloader 用于这些文件:

    此映射是通过扫描给定目录/文件中所有 .php 和 .inc 文件中的类来构建的。您可以使用类映射生成支持为所有不遵循 PSR-0/4 的库定义自动加载。要配置它,您需要指定所有目录或文件来搜索类。

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

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

    【讨论】:

    • 你是对的。这确实解决了部分问题,但是PSR-0 问题仍然存在(检查我的上次编辑)
    • @Norgul 我刚刚更新了我的答案,也许它可以帮助你。
    猜你喜欢
    • 2014-08-02
    • 2014-04-16
    • 2014-03-24
    • 2015-01-08
    • 2014-02-14
    • 2014-07-25
    • 2013-11-09
    • 2018-07-25
    • 1970-01-01
    相关资源
    最近更新 更多