支持多命名空间,但需正确配置psr-4结构:同一键下用不同前缀映射不同路径,路径值建议为数组,避免重名覆盖;psr-4优先于classmap;autoload-dev可覆盖主autoload同名类。

支持,但不是“随便加几个键就完事”。多命名空间能用,前提是配置结构正确、路径不重叠、且每次改完都运行 composer dump-autoload。
psr-4 里多个命名空间怎么写才不被覆盖
JSON 键名唯一,所以不能重复写同一个命名空间前缀;也不能把不同前缀拆成多个 psr-4 块——Composer 只认一个 psr-4 键,其余会被忽略。
- 错误写法:
"psr-4": { "App\": "src/", "App\": "app/" }→ 第二个App\被 JSON 解析器直接丢弃 - 错误写法:
"psr-4": { "App\": "src/" }, "psr-4": { "Tests\": "tests/" }→ 后一个psr-4覆盖前一个,只生效最后一个 - 正确写法:
"psr-4": { "App\": "src/", "Tests\": "tests/", "Vendor\Tool\": "vendor-tools/src/" } - 路径值必须是字符串或字符串数组;单路径也建议写成数组形式(兼容性更好):
"App\": ["src/"]
同一命名空间映射多个目录的写法和风险
可以,但得用数组值,不是多个键。比如让 MyApp\ 同时从 src/ 和 legacy/src/ 加载类。
- 写法:
"MyApp\": ["src/", "legacy/src/"] - 加载顺序:Composer 按数组顺序查找,
src/Services/User.php会优先于legacy/src/Services/User.php - 风险:两个目录里有同名类(如
MyApp\Services\User),只会加载第一个匹配到的,后面那个静默失效 - 替代建议:拆成子命名空间更安全,比如
"MyApp\": "src/", "MyApp\Legacy\": "legacy/src/"
psr-4 和 classmap 混用时谁先加载
PSR-4 匹配成功就立刻加载,根本不会走到 classmap;只有 PSR-4 完全不匹配(连命名空间前缀都没对上),才会查 classmap 表。
- 举例:你配了
"Legacy\": "legacy/",又在classmap里加了legacy/old.php,那LegacyOldClass仍会去找legacy/OldClass.php,而不是legacy/old.php - classmap 的真实用途:加载不符合 PSR-4 结构的文件,比如扁平工具函数、动态生成的桩文件、或遗留的
.php脚本 - 执行
composer dump-autoload -o后,所有规则合并进一张静态表,但逻辑不变:PSR-4 前缀匹配优先级永远高于 classmap 查表
autoload-dev 里怎么加测试命名空间
autoload-dev 的 psr-4 是独立块,可以和主 autoload 完全重复,但注册顺序靠后,所以它会“盖住”主 autoload 的同名类。
- 写法:
"autoload-dev": { "psr-4": { "Tests\": "tests/", "App\": "tests/mocks/" } } - 效果:当 PHPUnit 运行时,
App\Services\User如果同时存在于src/和tests/mocks/,会优先加载 mock 版本 - 注意:修改
autoload-dev后,要加-d参数更新:composer dump-autoload -d - 别指望它自动隔离——它只是多注册了一组 autoloader,顺序在主 autoload 之后
最容易被忽略的是路径结尾斜杠和命名空间结尾反斜杠:缺一不可。写成 "App": "src" 或 "App\": "src" 都会导致拼接路径出错,而且 Composer 不报错,只默默加载失败。


















