autoload-dev 必须配置在 composer.json 顶层 "autoload-dev" 字段下,与 "autoload" 并列;它专用于开发环境类加载,需配合 --dev 安装且通过 vendor/autoload.php 加载。

autoload-dev 配置不是用来“替代” autoload 的,而是专门给测试、工具类等仅在开发环境需要的代码加的独立加载规则——配错位置或混用 psr-4 与 classmap 容易导致 Class not found 却查不到原因。
autoload-dev 该写在哪?不是 composer.json 根目录随便加
必须写在 composer.json 的顶层 "autoload-dev" 字段下,和 "autoload" 并列,不能嵌套进 "require-dev" 或其他字段里。Composer 只认这个键名,拼错大小写(比如 autoloadDev)或放错层级,整个配置直接被忽略。
常见错误现象:phpunit 找不到测试类,但 composer dump-autoload 不报错,vendor/autoload.php 里也看不到对应映射。
- 正确位置示例:
{
"autoload": { "psr-4": { "App\": "src/" } },
"autoload-dev": { "psr-4": { "Tests\": "tests/" } },
"require-dev": { "phpunit/phpunit": "^10" }
}
psr-4 和 classmap 在 autoload-dev 里怎么选?看文件结构是否符合命名空间约定
psr-4 要求目录结构严格匹配命名空间,比如 Tests\Feature\UserTest 必须对应 tests/Feature/UserTest.php;而 classmap 是暴力扫描,适合放散装工具脚本、不走命名空间的 TestCase 基类、或第三方测试辅助类。
性能影响:每次 composer dump-autoload,classmap 会重新遍历整个目录,大项目明显变慢;psr-4 只记录前缀映射,快且可预测。
- 推荐组合:
— 测试用例统一用 "psr-4": { "Tests\": "tests/" }
— 工具类(如 tests/helpers.php、tests/bootstrap.php)单独用 "classmap": ["tests/helpers.php", "tests/bootstrap.php"]
运行时为什么 tests/ 下的类还是找不到?别忘了 dump-autoload 和自动加载时机
autoload-dev 的映射只注入到 vendor/autoload.php 中,但默认这个文件**不自动包含在生产环境加载链里**。所以 PHPUnit 这类工具必须显式 require 它,或者通过 Composer 自带的 autoloader 初始化逻辑触发。
常见错误场景:
- 自己写脚本跑测试,只 include
vendor/autoload.php—— 这个文件本身已含 dev 映射,没问题 - 用
php -d auto_prepend_file=vendor/autoload.php script.php—— 同样有效 - 但在 Web 请求中(如 Laravel 的 artisan tinker),如果没启用 dev 模式或没加载完整 autoloader,
Tests\*类就不可见
验证方式:执行 composer dump-autoload -v,看输出里是否出现 Generating autoload files for dev;再检查 vendor/composer/autoload_psr4.php 是否有你的 Tests\ 条目。
autoload-dev 和 require-dev 有啥关系?没有自动绑定,全靠你手动对齐
autoload-dev 和 require-dev 完全是两件事:前者管“哪些类能被 new 出来”,后者管“哪些包能被 composer install --dev 装上”。你可以在 require-dev 里装 phpunit,但如果不配 autoload-dev,PHPUnit 还是加载不了你自己写的 Tests\* 类。
容易踩的坑:
- 删掉
require-dev里的某个包,忘了同步清理autoload-dev里对应的映射,导致 dump-autoload 报 warning(但不中断) - CI 环境用了
--no-dev,此时autoload-dev映射压根不会写入vendor/autoload.php,所有 dev 类不可用 —— 这是预期行为,不是 bug
真正关键的是:只要你在本地开发或 CI 中运行测试,就必须确保 composer install 或 composer update 是带 --dev(默认开启)的,否则 autoload-dev 彻底失效。











