Class not found 是 Composer 未将类注册进自动加载表所致;应直接检查 vendor/composer/autoload_classmap.php 或 autoload_psr4.php 是否包含该类,配合 composer dump-autoload -v 查看扫描详情并手动清理旧映射文件。

“Class not found” 不是类文件丢了,而是 Composer 没把它注册进自动加载表 —— 直接看 vendor/composer/autoload_classmap.php 或 autoload_psr4.php 里有没有你的类名,比猜快十倍。
怎么确认类到底进没进 autoload 映射表
别跑代码看报错,先打开生成的映射文件:
vendor/composer/autoload_classmap.php(classmap 模式)
vendor/composer/autoload_psr4.php(PSR-4 模式)
用 Ctrl+F 搜你的完整类名(比如 AppServicesUserService),没出现就说明根本没被扫进去。
- 如果用了 classmap,但
autoload_classmap.php里没有该类名 → 说明扫描阶段就被跳过了 - 如果用了 PSR-4,但
autoload_psr4.php里没对应前缀(如"App\": ["src/"])→ 配置压根没生效 - 改了
composer.json后没删旧文件就直接dump-autoload,PHP 可能还在用 OPcache 缓存的旧映射
为什么 composer dump-autoload -v 是必跑命令
不加 -v 就像蒙眼操作:dump-autoload 成功了也不告诉你扫了哪些路径、跳过了什么文件、哪条配置被忽略。加了 -v 才能看到真实执行流:
- 逐行列出每个
classmap路径是否被读取(比如lib/出现在输出里,才说明配置被识别) - 显示某个 PHP 文件因语法错误、空文件或没声明类而被静默跳过(常见于
.php5或.inc文件混入目录) - 确认 PSR-4 前缀是否被解析(输出里要有类似
Adding PSR-4 autoload rule for App\: src/) - 如果某目录完全没出现在 -v 输出中,回头检查
composer.json的字段名(是不是写成class_map)、缩进(JSON 不认 tab)、尾逗号(多一个就整个 autoload 段失效)
classmap 和 PSR-4 冲突时谁说了算
classmap 查表永远在 PSR-4 推导之前,一旦类名出现在 autoload_classmap.php 里,Composer 就不会再走命名空间路径推导 —— 这是硬规则,不是可配选项。
- 你删了
src/Helper.php,但autoload_classmap.php还留着它 →new Helper()仍能通过自动加载,只是运行时报include(): failed to open stream - 你同时配了
"App\": "src/"和"lib/"到 classmap,且lib/Utils.php里定义了class Utils→new Utils()走 classmap,new AppServicesUserService()才走 PSR-4 - 想强制让某类走 PSR-4?必须确保它不在
autoload_classmap.php中 —— 删掉 classmap 条目,再dump-autoload,别只删文件不删映射
删 autoload 文件比重跑命令更重要
很多人重跑十遍 composer dump-autoload 还是失败,因为旧映射文件还躺在那里,OPcache 或 APCu 可能正拿着它的字节码跑。
- 必须手动删掉:
vendor/composer/autoload_classmap.php、autoload_static.php(优化模式下生成,优先级更高)、autoload_files.php(如果用了files加载) - 别只删
autoload_classmap.php却留着autoload_static.php,后者会绕过你刚生成的新映射 - 删完再跑
composer dump-autoload -v,观察输出是否包含你期望的路径和类,而不是依赖“应该没问题”这种感觉
最易被忽略的点:PSR-4 命名空间末尾少一个反斜杠("App": "src/" ❌ 应为 "App\": "src/"),或者 classmap 路径写了 "./lib/"(必须是相对路径 "lib/"),这类拼写错误不会报错,但会让整条规则静默失效。


















