Class not found 主因是本地包 PSR-4 配置错误:命名空间末尾缺双反斜杠、路径开头含 ./、目录结构与命名空间不匹配,且改后未在主项目根目录执行 composer dump-autoload。

本地包的composer.json必须配对psr-4且路径严格对齐
类找不到,第一反应不是 Composer 没装好,而是本地包自身的 autoload 配置错了。PSR-4 不是“大概能找着”,它按字符串拼接定位文件:命名空间末尾的双反斜杠 、路径末尾的正斜杠 /、目录/文件名大小写,三者缺一不可。
常见错误示例:
-
"MyVendorMyPackage": "src/"→ 缺少末尾反斜杠,会被当 PSR-0 处理 -
"MyVendorMyPackage": "./src"→ 路径开头带.,部分环境解析失败 - 命名空间是
MyVendorMyPackageUtils,但文件实际在src/MyPackage/Utils.php→ 多了一层MyPackage目录,路径不匹配
正确写法示例:
"autoload": {
"psr-4": {
"MyVendor\MyPackage\": "src/"
}
}
注意:\ 是 JSON 中转义后的单个反斜杠,最终效果是 MyVendorMyPackage。
改完autoload后必须运行composer dump-autoload
Composer 不会监听文件变化,也不会在 require 或 install 时自动重生成映射。你改了本地包的 composer.json,哪怕只加了一个空格,也得手动触发重新生成加载器。
- 在主项目根目录执行
composer dump-autoload(开发阶段不用--optimize) - 检查
vendor/composer/autoload_psr4.php是否已更新,确认你的命名空间出现在数组里 - 如果用的是 Laravel,别漏掉
php artisan config:clear(仅当缓存了配置时影响 ServiceProvider 加载)
为什么classmap或files字段有时更合适
PSR-4 强依赖命名空间与目录结构的一致性。如果你的本地包里有全局函数、Traits、或者类散落在非标准路径(比如 legacy/、helpers/),硬套 PSR-4 反而增加维护成本。
-
classmap:适合无命名空间的老代码,配置"classmap": ["legacy/", "helpers/"]后,dump-autoload会扫描所有.php文件并建映射,不看命名空间 -
files:适合纯函数文件,如"files": ["src/helpers.php"],它会在vendor/autoload.php初始化时无条件include_once,但要注意副作用和加载顺序不可控 - 二者都要求路径相对于主项目
composer.json,不能写./src/helpers.php或src/helpers(缺.php)
本地包装进vendor后仍Class not found?先查autoload注册链
即使 composer require acme/my-utils:dev-main 成功,且包目录已出现在 vendor/acme/my-utils,类仍可能加载失败——因为 Composer 只负责把包复制进去,不负责把它的 autoload 注册进主项目的自动加载器。
- 确认本地包的
composer.json里真有autoload段,且格式合法(JSON 语法正确、字段名拼写正确) - 运行
composer show acme/my-utils,看输出里是否包含autoload信息;若没有,说明 Composer 根本没读取到该包的 autoload 配置 - 检查
vendor/composer/autoload_psr4.php,搜索你的命名空间前缀,不在里面就说明没注册成功 - Laravel 用户额外注意:Service Provider 和 Facade 仍需手动在
config/app.php中注册,Composer 不处理这部分
最容易被忽略的是:本地包改了 autoload,但只在包目录里 dump-autoload,没在主项目里执行——这一步必须在主项目根目录做。











