autoload-dev 中 classmap 与 psr-4 混用会失效,因 psr-4 优先匹配且不 fallback;须单选其一并确保路径/命名空间严格一致,修改后需执行 composer dump-autoload –dev 生效。

autoload-dev 里 classmap 和 psr-4 混用会失效
很多人把测试类路径同时写进 classmap 和 psr-4,结果 phpunit 找不到测试类——Composer 的 autoload-dev 加载规则是“先匹配到谁就用谁”,psr-4 优先级高于 classmap,但若命名空间不严格对应目录结构,psr-4 匹配失败后也不会 fallback 到 classmap。
正确做法是只选一种,且确保路径与命名空间一致:
- 用
psr-4:测试类必须在tests/下,且命名空间以Tests开头(如TestsUnitExampleTest对应tests/Unit/ExampleTest.php) - 用
classmap:适合老项目或非标准结构,直接指向含测试类的目录,无需命名空间约束,但每次增删文件后要手动执行composer dump-autoload --dev
修改 composer.json 后必须重新生成 autoloader
改完 autoload-dev 不运行命令,新配置完全不生效。Composer 不会在每次 require 时动态解析 composer.json。
关键命令只有两个:
-
composer dump-autoload --dev:仅重新生成开发依赖的自动加载映射(推荐日常使用) -
composer install --no-autoloader && composer dump-autoload --dev:适用于 CI 环境或怀疑主 autoloader 被污染时
验证是否生效:查看 vendor/composer/autoload_dev.php 文件末尾,确认你的路径或命名空间映射已写入数组中。
PHPUnit 启动时报 Class not found?检查 vendor/autoload.php 是否被正确引入
很多测试脚本(尤其是自定义启动逻辑)直接 require 'vendor/autoload.php',但这只加载 autoload(生产代码),不包含 autoload-dev。结果就是测试类明明配了,却报 Class 'TestsUnitExampleTest' not found。
解决方案分场景:
- 用
phpunit.xml配置:确保存在 —— 这个autoload.php是 Composer 生成的完整入口,已合并 dev 配置 - 命令行直接跑:用
php -d auto_prepend_file=vendor/autoload.php vendor/bin/phpunit tests/,避免手写 require - 写测试引导文件:必须
require __DIR__.'/vendor/autoload.php';,不能只 require 生产 autoload 文件
{ "autoload": { "psr-4": { "app\": "src/" } }, "autoload-dev": { "psr-4": { "Tests\": "tests/" } } }
测试类文件位置和命名空间必须严格对应:tests/Unit/ExampleTest.php 内必须声明 Namespace TestsUnit;。少一个反斜杠、多一个空格,psr-4 就不会加载它。
最容易被忽略的是:CI 环境下 composer install 默认跳过 autoload-dev,除非明确加 --dev 或设置 COMPOSER_DEV_MODE=1。没这一步,整个 autoload-dev 配置形同虚设。