autoload-dev 必须作为 composer.json 顶层字段与 autoload 并列,拼写错误、嵌套或位置错误会导致配置静默失效;它与 autoload 完全独立,仅在开发环境生效,修改后需手动执行 composer dump-autoload --dev 才能更新映射。

autoload-dev 必须是 composer.json 顶层字段,拼错或嵌套就失效
Composer 只认 autoload-dev 这个精确键名,且必须和 autoload 并列写在 composer.json 根对象下。任何偏差都会导致整个配置被静默忽略——不报错、不警告、也不生成映射。
常见错误包括:
- 写成
autoloader-dev、autoload_dev或autoloadDev - 放在
require-dev或extra里(例如"require-dev": { "autoload-dev": {...} }) - 缩进错误导致 JSON 解析失败(如多了一层花括号)
验证是否生效的最快方式:运行 composer dump-autoload --dev -v,看终端输出是否列出你的 PSR-4 映射项;没列,就是配置位置错了。
autoload-dev 不是 autoload 的子集,它完全独立于生产加载逻辑
autoload-dev 和 autoload 是两套平行通道,互不继承、不合并、也不覆盖。你把测试类放进 autoload-dev,不代表它们会出现在生产环境的 vendor/autoload.php 中——但前提是,你没犯上面那个“配置位置错”的致命错误。
关键影响点:
- 运行
composer install --no-dev时,autoload-dev的规则不会写入任何映射文件 - 即使你执行了
composer dump-autoload --dev,生成的 PSR-4 条目也只写进vendor/composer/autoload_psr4.php,而vendor/autoload.php默认不加载这些条目——除非你在测试启动脚本(如tests/bootstrap.php)里显式require它 - 线上报
Class MockeryMockInterface not found却没装 mockery?大概率是autoload-dev配错位置,导致它的命名空间被意外塞进了生产映射表
修改 autoload-dev 后必须手动执行 dump-autoload --dev
Composer 不监听 composer.json 变更,也不会在 composer install 时自动重生成开发环境映射。改完 autoload-dev,必须显式运行:
composer dump-autoload --dev
否则新增的测试类永远无法被 PHPUnit 或其他开发工具识别。注意:
- 不加
--dev参数,只刷新autoload,autoload-dev的改动不会生效 - 加
-o(即composer dump-autoload --dev -o)会启用优化模式,此时autoload_psr4.php可能为空——这是正常行为,优化版走的是静态 classmap,不是动态 PSR-4 匹配 - 想确认是否写入成功,直接打开
vendor/composer/autoload_psr4.php,搜索你的命名空间前缀(如"Tests\"),有对应路径才说明生效
autoload-dev 支持的加载方式和典型用法
autoload-dev 支持和 autoload 完全相同的三种方式:psr-4、classmap、files,但语义上专用于开发阶段。
典型配置示例:
"autoload-dev": {
"psr-4": {
"Tests\": "tests/",
"Example\Test\": "examples/tests/"
},
"classmap": ["stubs/"],
"files": ["tests/helpers.php"]
}
使用场景与注意事项:
-
psr-4最常用,但要求Tests\TestCase对应tests/TestCase.php,大小写和路径必须严格匹配 -
classmap适合扫描无命名空间的老测试类(比如纯 function + class 混写的 legacy test 文件) -
files加载的是函数文件,不是类;tests/helpers.php必须定义在全局作用域,不能包在 namespace 里,否则函数不可见 - 不要把
tests/bootstrap.php放进files——它本身是启动入口,不是供自动加载的函数库
最易被忽略的一点:autoload-dev 的映射不会自动参与 HTTP 请求生命周期。它只服务于 CLI 场景(PHPUnit、PHPStan、PsySH 等),Web 请求中哪怕你 require 了 vendor/autoload.php,也不会加载 autoload-dev 里的类——除非你手动把它 merge 进去,而这违背了隔离设计初衷。











