classmap 是 Composer 处理无命名空间、类名与文件名不一致或类定义在 .inc 文件中的唯一方案;需在 composer.json 的 autoload.classmap 中配置路径数组,且新增文件后必须手动执行 dump-autoload。

classmap 是什么,什么时候必须用它
classmap 不是“另一种自动加载方式”,而是 Composer 唯一能处理**无命名空间、类名与文件名不一致、甚至类定义在 .inc 文件里**的方案。PSR-4 会直接跳过这些文件——它只认 namespace 和严格路径拼写。你项目里有 MyDB.php 定义了 Database 类?或者 config.php 里写了 class ConfigLoader 却没命名空间?那就只能靠 classmap。
怎么在 composer.json 里配 classmap
在 composer.json 的 "autoload"(或 "autoload-dev")下加 "classmap" 字段,值是一个路径数组:
{
"autoload": {
"classmap": [
"lib/",
"includes/functions.php",
"legacy/DB_*.php"
]
}
}
- 目录会被递归扫描所有
.php、.inc、.hh文件(注意:不扫.txt或.sql) - 支持 glob 表达式(如
legacy/DB_*.php),但不支持**递归通配符 - 路径必须真实存在,否则
composer dump-autoload会报 warning(但继续执行) - 大小写敏感:Windows/macOS 可能不报错,但部署到 Linux 就找不到类——务必保持文件名与类名大小写完全一致
执行 dump-autoload 后,映射存在哪、怎么查
运行 composer dump-autoload 后,结果存进 vendor/composer/autoload_classmap.php,内容就是一个大 PHP 数组:
return [ 'Database' => $vendorDir . '/myproject/lib/MyDB.php', 'ConfigLoader' => $vendorDir . '/myproject/includes/config.php' ];
- 键是类名(全大写标准化,不区分大小写注册,但建议别依赖这点)
- 值是绝对路径,
$vendorDir是 Composer 自动替换的常量 - 这个文件会被
vendor/autoload.php加载,然后在spl_autoload_register回调里直接查表require - 它不解析
class_alias(),也不识别动态eval("class X {}"),只认静态声明
classmap 和 PSR-4 同时存在时谁生效
Composer 会先走 PSR-4 匹配,没命中才查 classmap 表——也就是说,如果你同时配置了:
"psr-4": { "App\\": "src/" },
"classmap": [ "legacy/" ]
-
new App\Controller\UserController→ 走 PSR-4,去src/Controller/UserController.php -
new Database→ PSR-4 找不到前缀匹配,再查 classmap 表,命中legacy/MyDB.php - 但如果
Database也出现在src/下(比如你误放了一个同名类),PSR-4 会优先加载它,classmap 彻底被绕过 - 想强制只用 classmap?加
--classmap-authoritative参数,它会让加载器“查不到就放弃”,彻底跳过其他机制
最常被忽略的一点:classmap 不会自动感知新增文件——改了代码、加了新类,必须手动再跑一次 composer dump-autoload,否则新类永远不可用。










