Composer自动加载 - 从父目录加载类

8
我目前正在处理一个 Laravel 项目,需要访问其父目录中的类。
composer.json > PSR-4:
    "psr-4": {
        ...
        "ModuleA\\": "../ModuleA/baseObjects",
        "ModuleB\\": "../ModuleB/baseObjects"
    }

示例文件结构:

/var/www
 +- /xxx (project)
     +- /ModuleA
        +- /baseObjects
            - configClass.inc
     +- /ModuleB
        +- /baseObjects
            - configClass.inc
     +- /laravel
        - composer.json

我运行了 composer dump-autoload,但项目仍然找不到 ModuleA\configClassModuleB\configClass
此外,在我的 autoload_psr4.php 中,以上内容被引用如下:
'MobuleA\\' => array($baseDir . '/../MobuleA/baseObjects')
'MobuleB\\' => array($baseDir . '/../MobuleB/baseObjects')

尝试使用以下代码:"": "src(主文件夹,我猜是它)/",无需初始化模块,只需添加文件夹和 / 即可。 - DaAmidza
5个回答

4

PSR-4要求加载的文件具有命名空间类,并且命名空间结构必须与相对于配置中定义的“基目录”的目录结构匹配(http://www.php-fig.org/psr/psr-4/)。

因此,在文件/var/xxx/ModuleA/baseObjects/configClass.inc中应该是该类。

namespace ModuleA\baseObjects;

class configClass {
    ...
}

那么在 var/www/laravel/composer.json 文件中,您可以有以下内容:

    "psr-4": {
        "App\\": "app/",
        "ModuleA\\": "../ModuleA"
    }

这意味着:"目录../ModuleA应该是ModuleA命名空间的根,然后通过从那里匹配子目录来跟随子命名空间。"

3
使用类映射自动加载可以解决这个问题。
{
...
"autoload": {
        "classmap": ["ModuleA/", "ModuleB/"]
    }
}

可以与PSR-4一起使用。
{
    ...
    "autoload": {
            "psr-4": { 
                "Acme\\": "src/Acme/"
            },
            "classmap": ["ModuleA/", "ModuleB/"]
        }
    }

参考: https://getcomposer.org/doc/04-schema.md#classmap

该文档介绍了Composer中的classmap选项,它允许您手动指定需要包含在自动加载器中的类文件。这对于一些没有遵循PSR-0或PSR-4标准的老代码库非常有用。


2
您遇到的问题与父目录无关。实际上,您的Composer.json自动加载配置对于您的目录结构是正确的。
问题在于“.inc”文件扩展名与PSR-4规范不兼容。更多信息请参见:如何使Composer(PSR-4)与“.class.php”扩展名一起工作? 如果您无法更新源代码以符合PSR-4规范,则可以使用类映射

在安装/更新期间,所有类映射引用都将组合成一个单独的键=>值数组,该数组可以在生成的文件vendor/composer/autoload_classmap.php中找到。此映射是通过扫描给定目录/文件中的所有.php.inc文件中的类来构建的。

您可以使用类映射生成支持为所有不遵循PSR-0/4的库定义自动加载。要配置此项,您需要指定要搜索类的所有目录或文件。

因此,您的配置可能如下所示:
"autoload": {
    "classmap": [
        "../ModuleA/baseObjects",
        "../ModuleB/baseObjects"
    ]
}

请记住,如果您使用类映射(class mapping),则需要在更改composer.json、添加类、修改类名称/文件名/路径等任何时候运行composer dump-autoload
额外提示:如@alepeino指出的那样,使用自动加载优化将从任何PSR-0和PSR-4自动加载定义生成一个类映射,使用与classmap自动加载相同的基础代码。这将“允许”您使用PSR-4自动加载器和.inc扩展名。但是,这仍然需要每次进行文件更改时运行composer dump-autoload --optimize,就像classmap一样。
最好的建议是:更改您的源代码以遵循PSR-4规范,并使用.php扩展名。
如果无法这样做,则使用classmap进行自动加载是下一个最佳选择。

我也是这么想的,所以我尝试了一下,发现虽然 PSR-4 规范说文件扩展名“必须”是“.php”,但 Composer 实际上可以正确加载“.inc”文件。 - alepeino
我想看看你用于测试的代码。我进行了基本的PSR-4设置,匹配了相关的目录结构,然后将其中一个类扩展名更改为".inc",但是无法找到该类。自动加载器显式地设置了扩展名。也许是Composer版本不同导致的问题? - Aken Roberts
事实证明,我在一个 Laravel 项目中进行了第一次测试,然后又尝试在一个全新的临时项目中进行测试,但都无法正常工作。我的原始 composer.json 文件中有 optimize-autoloader。请参见 https://github.com/alepeino/composer-optimize。 - alepeino
啊哈!再次查看Composer的源代码,optimize-autoloader和等效命令最终会在所有PSR-0和PSR-4目录上运行类映射器,该映射器将查找.inc扩展名的文件。 - Aken Roberts

0

试一下:

"psr-4": {
        ...
        "ModuleA\\": "ModuleA/baseObjects",
        "ModuleB\\": "ModuleB/baseObjects"
 }

它不起作用,上面的代码试图在当前目录中查找它,而我正在尝试访问父目录。 - davidvnog

0

根据这个答案,您可以将它添加到index.php文件中:

$loader = require 'vendor/autoload.php';
$loader->add('Namespace\\Somewhere\\Else\\', __DIR__);
$loader->add('Namespace\\Somewhere\\Else2\\', '/var/www/html/xxx');

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