composer 2.x 完全移除 psr-0 支持,psr-0 配置被忽略,类加载失败;应改用 classmap 或手动通过 spl_autoload_register 实现兼容。

Composer 2.x 根本不支持 PSR-0 自动加载
直接说结论:composer install 或 composer dump-autoload 在 Composer 2.0+ 中完全忽略 psr-0 配置项,不会生成任何对应映射逻辑。这不是配置没写对,而是代码层已移除——你看到的 "psr-0": {...} 在 composer.json 里纯属无效字段。
典型现象是:类文件明明在 library/Zend/Controller/Action.php,类名是 Zend_Controller_Action,路径也符合 PSR-0 规则,但运行时仍报 Class 'Zend_Controller_Action' not found。原因就是 autoload 机制压根没注册这条规则。
- Composer 从 2.0 开始正式废弃 PSR-0(PHP-FIG 早在 2014 年就弃用了)
-
vendor/autoload.php加载后,get_declared_classes()里查不到这些类,说明根本没进加载流程 - 即使你在
autoload-dev里写psr-0,同样被跳过
手动补 PSR-0 加载器:用 spl_autoload_register 实现兼容
既然 Composer 不干这事,就得自己在 PHP 运行时补上。核心是写一个符合 PSR-0 规范的加载回调函数,在引入 vendor/autoload.php 后立即注册。
关键点不是“能 require 文件”,而是严格还原 PSR-0 的转换逻辑:下划线 _ → 目录分隔符,全小写文件名,多级前缀支持(如 MyOrg_Package_ClassName → myorg/package/classname.php),且必须检查文件存在性。
- 必须放在
require_once __DIR__ . '/vendor/autoload.php';之后,否则会被 Composer 的加载器抢先拦截 - 要加
class_exists($class, false)和interface_exists(...)检查,避免重复加载或干扰内置类 - 路径拼接必须准确:
__DIR__ . '/vendor/myorg/package/lib/' . $filename—— 这里的lib/是示例,得按你实际目录调整 - Windows 下大小写不敏感,Linux/macOS 敏感:如果文件叫
Db_Mysql.php,但类声明是class db_mysql,就会失败
更稳妥的替代方案:改用 classmap
如果你的旧库类数量少、结构固定(比如就 5–10 个 PEAR 风格类),classmap 是比手写 autoload 更可靠的选择。它不依赖命名规则,只做静态文件扫描 + 类名到路径的硬映射。
例如 library/DB/Mysql.php 里有 class DB_Mysql,只需在 composer.json 里加一行:
{
"autoload": {
"classmap": ["library/"]
}
}
然后执行 composer dump-autoload -o(加 -o 生成优化版映射,性能更好)。
-
classmap兼容无命名空间、下划线类名、甚至单文件多类等所有“不守规矩”的情况 - 缺点是无法加载运行时动态拼接的类名(比如
$class = $prefix . '_Adapter'; new $class;) - 注意路径必须包含所有含类定义的 .php 文件;漏掉某个子目录,里面的类就找不到
- 修改后必须手动运行
composer dump-autoload,否则更改不生效
别踩这些坑:混合配置、路径错位、大小写陷阱
很多人试过在 autoload 里同时写 psr-4 和 psr-0,以为能共存。结果发现 PSR-0 条目静默失效,或者类加载错乱——这不是 bug,是 Composer 明确禁止的行为。
- Composer 不允许同一
autoload块中混用psr-0和psr-4;遇到时会直接忽略psr-0,只保留psr-4 - PSR-4 路径不能包含命名空间片段:比如
"Zend\": "library/Zend/"是错的,正确应为"Zend\": "library/",且文件必须在library/Zend/Controller/Action.php - PSR-0 路径必须含完整前缀子目录:
"Zend_": "library/Zend/"意味着Zend_Controller_Action对应library/Zend/Controller/Action.php - Linux/macOS 下,
DB_Mysql.php里写class db_mysql就会加载失败——类名和文件名大小写必须完全一致
最常被忽略的是:你以为改了 composer.json 就完事了,其实没跑 composer dump-autoload,映射根本没更新。这个命令不是可选的,是必做的一步。










