Composer 2.0+ 完全移除 PSR-0 支持,psr-0 字段被静默忽略;旧包需手动用 spl_autoload_register() 补加载逻辑或改用 classmap。

Composer 2.0+ 根本不支持 PSR-0 自动加载
直接说结论:composer install 或 composer dump-autoload 在 Composer 2.0 及更高版本中,**完全忽略 "psr-0" 字段**,也不会生成任何 PSR-0 映射逻辑。这不是配置没写对,而是功能已被硬性移除。
常见错误现象:Class 'MyPackage_Utils' not found,类文件明明在 vendor/myorg/package/lib/mypackage/utils.php,命名、路径、下划线转斜杠规则都符合 PSR-0,但 vendor/autoload.php 就是不加载它——因为 Composer 根本没注册这条规则。
- PSR-0 已被 PHP-FIG 官方弃用(2014 年),Composer 从 v2.0 起彻底删除支持
- 即使你在
composer.json里写了"psr-0",Composer 会静默跳过,不报错也不警告(除非你用--verbose) - 不存在“开启兼容开关”或“降级配置项”这种操作;
composer require --no-plugins或改minimum-stability都无效
必须手动补 PSR-0 加载器(仅限 runtime 层)
如果你确实要跑一个只遵循 PSR-0 的旧包(比如 swiftmailer/swiftmailer:v5.x 或某些 PEAR 包),唯一可行路径是在 PHP 运行时用 spl_autoload_register() 补一条加载逻辑——不是改 Composer 配置,而是在项目入口手动注册。
关键点:必须严格还原 PSR-0 规则,不能简单 require_once 所有文件。
- 下划线
_必须转为目录分隔符/,且全部小写(Foo_Bar_Baz→foo/bar/baz.php) - 需支持多级前缀(
MyOrg_Package_Class→myorg/package/class.php) - 必须检查
file_exists(),避免重复加载或触发 warning - 务必放在
require_once 'vendor/autoload.php'之后,否则会被 Composer 的 PSR-4 加载器抢先拦截
示例(放入 index.php 或 bootstrap.php):
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
require_once __DIR__ . '/vendor/autoload.php';
spl_autoload_register(function ($class) {
if (false === strpos($class, '_') || class_exists($class, false) || interface_exists($class, false)) {
return;
}
$parts = explode('_', $class);
$file = __DIR__ . '/vendor/myorg/package/lib/' . strtolower(implode('/', $parts)) . '.php';
if (is_file($file)) {
require_once $file;
}
});
更推荐:改用 classmap 加载少量固定类
如果这个 PSR-0 类库结构稳定、文件不多(比如就 3–5 个类),用 classmap 比手写 autoload 更可靠、更易维护,也避免运行时路径拼错或大小写问题。
原理:Composer 扫描指定目录,把每个 .php 文件里的 class/interface/trait 名字和物理路径记进 autoload_classmap.php,后续直接查表,不走字符串解析。
- 在
composer.json中添加:"classmap": ["vendor/myorg/package/lib/"] - 执行
composer dump-autoload -o(加-o强制生成 classmap) - 注意路径必须真实存在,且相对
composer.json;不要包含通配符或变量 - 不支持动态类名或运行时生成的类,但对静态遗留代码来说,这是最稳的方案
别踩坑:PSR-0 和 PSR-4 绝对不能混配
试图在同一个 "autoload" 块里同时写 "psr-0" 和 "psr-4",结果只会是:PSR-0 被静默丢弃,只生效 PSR-4,还可能收到弃用警告。
更隐蔽的问题是命名空间重叠——比如你定义了 "App\": "src/"(PSR-4),又想让 "App_Foo_Bar" 走 PSR-0,那只要类名匹配 App 前缀,PSR-4 加载器就会先尝试找 src/Foo/Bar.php,根本不会留给 PSR-0 处理机会。
- Composer 不允许混合声明;这不是 bug,是设计上强制隔离
- 不要指望通过调整
psr-0和psr-4的顺序来控制优先级 - 若必须共存,唯一办法是把 PSR-0 类库完全隔离(如单独放
legacy/目录),用classmap或files加载,不参与主 autoload 流程
真正麻烦的从来不是怎么写配置,而是确认那个类到底该由谁加载——一旦混淆,Cannot declare class X 或 Class not found 就会反复出现,而且很难定位到根源。

















