composer支持同时配置psr-4、psr-0、classmap和files四类autoload规则,按声明顺序合并生效;psr-4多路径需用数组表示,命名空间不可嵌套,路径须为相对路径且不以斜杠结尾。

composer.json 里怎么写多个 autoload 配置项
Composer 支持在同一项目中同时配置 "psr-4"、"psr-0"、"classmap" 和 "files" 四类自动加载规则,它们会按声明顺序合并生效,不存在覆盖关系。关键不是“能不能加多个”,而是“加在哪、怎么组织才不冲突”。
常见错误是把不同路径的 PSR-4 映射硬塞进同一个数组键下,导致后写的被前写的覆盖(因为 jsON 键名唯一):
{ "autoload": { "psr-4": { "app\": "src/", "App\": "app/" ← 这行无效:键重复,会被上一行覆盖 } } }
正确做法是合并到同一组映射中:
{ "autoload": { "psr-4": { "App\": ["src/", "app/"], "Vendor\Tools\": "vendor-tools/src/", "Tests\": "tests/" } } } psr-4 的值必须是数组(即使只有一条路径),多路径用列表形式表达 - 不同命名空间前缀不能互相包含(如
"A\" 和 "A\B\" 共存时,A\B\X 类可能被错误匹配到 A\ 规则下) - 路径必须是相对于
composer.json 所在目录的相对路径,且结尾不带斜杠("src" ✅,"src/" ❌ 在某些旧版本会报 warning)
PSR-4 和 classmap 混用时谁优先
Composer 自动加载器按注册顺序查找类:先查 psr-4,再查 psr-0,然后是 classmap,最后是 files。但实际执行中,**PSR 规则一旦命中路径就立即尝试加载文件,不会退回到 classmap**;只有 PSR 规则完全不匹配时,才会继续走 classmap。
立即学习“PHP免费学习笔记(深入)”;
这意味着:
- 如果你在
psr-4 中写了 "Legacy\": "legacy/",又在 classmap 中包含了 legacy/old.php,那么 LegacyOldClass 仍会走 PSR-4 加载逻辑(即找 legacy/OldClass.php),不会自动 fallback 到 classmap - classmap 更适合加载不符合 PSR 标准的散装类、函数文件,或需要预生成映射提升性能的场景(如大型遗留模块)
- 运行
composer dump-autoload -o 会把所有规则合并进一个优化后的 autoload_classmap.php,此时加载顺序差异消失,但映射关系不变
如何让 tests 目录下的测试类也能被自动加载
默认情况下,tests/ 不参与生产环境 autoload,但 PHPUnit 运行时需要加载测试类。最稳妥的方式是单独为测试类配置 autoload(开发专用):
{ "autoload-dev": { "psr-4": { "Tests\": "tests/" } } }
注意:autoload-dev 中的规则**只在 composer install --dev(默认)或 composer update 时生效**,线上部署用 composer install --no-dev 会跳过它。
- 不要把测试类放进
autoload(主 autoload),否则生产环境也会加载,可能引发依赖或安全问题 - 如果测试类依赖某些仅 dev 下存在的包(如
phpunit/phpunit),它们的 autoloading 由各自autoload-dev管理,无需额外处理 - 某些框架(如 laravel)约定测试类用
Tests\Feature\/Tests\Unit\前缀,这时需确保Tests\映射覆盖全部子目录
修改命名空间后 composer dump-autoload 没生效?检查这三处
改完 composer.json 后运行 composer dump-autoload 却发现类还是找不到,大概率卡在这几个地方:
- 没删掉
vendor/autoload.php引入前已存在的手动 require / include —— Composer autoloader 是懒加载,手动引入会绕过它 - PHP opcode 缓存(如 OPcache)未清除,导致旧的 autoload 文件被缓存,可临时加
opcache_reset()或重启 PHP-FPM - 类文件名大小写不一致(尤其在 windows/macOS 开发、linux 部署时):PSR-4 要求严格匹配,
MyClass.php里定义MyClass✅,但myclass.php里定义MyClass❌
调试技巧:运行 composer dump-autoload -v 查看详细映射输出,或直接打开 vendor/composer/autoload_psr4.php 确认你的命名空间是否已写入。