psr-0在composer.json中需写为autoload.psr-0键下命名空间到路径的数组映射,如{"mylib\": "src/"},路径须真实存在且文件结构与命名空间严格匹配,否则类无法加载。

PSR-0 在 composer.json 里怎么写才有效
PSR-0 已被废弃,但老项目升级时仍需兼容。关键不是“能不能用”,而是“用对了没”——autoload.psr-0 必须是顶层 autoload 下的键,且值必须是命名空间到路径的映射(数组),不能是字符串或嵌套结构。
- 错误写法:
"autoload": { "psr-0": "src/" }(缺少命名空间前缀) - 正确写法:
"autoload": { "psr-0": { "MyLib\": "src/" } }(命名空间末尾带双反斜杠,路径相对 composer.json) - 多个命名空间可并列:
{"MyLib\": "src/", "Tests\": "tests/"} - 空字符串作为命名空间前缀(全局根命名空间)允许但不推荐:
{"": "legacy/"},容易和 PSR-4 冲突
为什么 dump-autoload 后类还是找不到
常见原因是路径未实际存在,或命名空间声明与文件结构不匹配。PSR-0 要求:命名空间 MyLibUtilStringHelper 必须对应文件 src/MyLib/Util/StringHelper.php(注意大小写敏感,尤其在 Linux/macOS)。
- 检查
src/MyLib/Util/StringHelper.php是否真实存在,且首行有namespace MyLibUtil; - 运行
composer dump-autoload -v查看是否报错,比如 “Class MyLibUtilStringHelper is not autoloadable” - 确认没有同时配置了
autoload.psr-4覆盖同名空间(PSR-4 优先级更高,会静默忽略 PSR-0) - Windows 下路径分隔符不用改,Composer 自动处理;但文件名大小写仍需严格匹配
PSR-0 和 PSR-4 混用时要注意什么
可以共存,但必须避免同一命名空间被两个规则同时覆盖,否则行为不可控。Composer 不会报错,但加载顺序可能导致类从错误路径加载。
- 例如:
"psr-0": { "MyLib\": "src-old/" }和"psr-4": { "MyLib\": "src/" }共存 →MyLibFoo总从src/加载,src-old/彻底失效 - 若要逐步迁移,建议先用
psr-0覆盖全部旧代码,再为新模块单独加psr-4规则,且命名空间不重叠 -
composer dump-autoload --optimize会生成静态映射,此时 PSR-0 映射仍生效,但性能不如 PSR-4
PHP 8+ 或现代框架里还该用 PSR-0 吗
不该。Composer 2.0+ 对 PSR-0 的支持只是向后兼容,不再修复相关 bug;Laravel、Symfony 等已完全移除 PSR-0 文档和测试用例。强行保留只会拖慢 autoloader 初始化,并增加维护成本。
- 替换方案:把
src/MyLib/Util/StringHelper.php的命名空间改成MyLibUtil不变,但目录结构改为src/Util/StringHelper.php,然后切到psr-4 - 工具辅助:
php-cs-fixer可批量重写命名空间,但路径需手动调整 - 最隐蔽的坑:某些老扩展(如 PHPUnit 4.x 插件)依赖 PSR-0,升级前先确认测试能否跑通
真正麻烦的不是配置本身,而是那些没写进 composer.json 的硬编码 require 或 spl_autoload_register 回调——它们不会随 dump-autoload 更新,得一个个翻源码。










