离线环境下class not found是因autoload映射未更新,需强制dump-autoload、检查路径与命名空间冲突、清除opcache并验证classmap是否包含目标类。

composer install 时提示 Class not found,但 vendor 已存在
离线环境下,composer install 可能跳过 autoload 重生成,导致 vendor/autoload.php 里没注册新包或路径变更后的类。这不是文件缺失,而是自动加载映射(vendor/composer/autoload_classmap.php 等)没更新。
- 先确认是否真离线:运行
composer install --no-scripts --no-plugins强制重走安装流程,避免脚本干扰 - 手动触发 autoload 重建:执行
composer dump-autoload --optimize(注意:离线时别加--classmap-authoritative,它会删掉 PSR-4 回退逻辑,反而让某些动态加载失败) - 检查
composer.json中的autoload和autoload-dev是否含本地路径(如"src/": ["src"]),离线时这些路径必须真实存在且未被 .gitignore 误删
多个包声明相同命名空间,autoload 优先级混乱
离线时无法靠 composer 自动 resolve 冲突,composer dump-autoload 会按 composer.json 里 require 的顺序合并映射,后加载的包可能覆盖先加载的同名类。
- 用
composer show --tree(需提前在线运行并保存输出)比对依赖树,确认冲突来源是直接 require 还是 transitive 依赖 - 在
autoload段显式排除冲突路径:"exclude-from-classmap": ["vendor/bad/pkg/src/ConflictClass.php"] - 若必须共存,改用
files方式加载关键类:"autoload": {"files": ["vendor/good/pkg/helpers.php"]},绕过 classmap 冲突
离线时 vendor/composer/autoload_static.php 被缓存旧版本
这个文件是 dump-autoload --optimize 生成的静态映射,PHP opcache 或 APCu 可能缓存了它的字节码,导致改完 composer.json 后仍加载旧类路径。
- 重启 PHP-FPM 或 Web 服务器(不是 reload,是 stop + start),清空 opcache:
opcache_reset()或调用php -r "opcache_reset();" - 临时禁用 opcache 验证:把
opcache.validate_timestamps=1加进 php.ini,离线调试时更可控 - 检查
vendor/composer/autoload_static.php文件修改时间,和composer.json修改时间对比,不一致说明 dump 没生效
为什么 vendor/autoload.php 有时“看起来生效”但实际没加载?
常见假象:require vendor/autoload.php 不报错,但 new 某个类仍 Class not found。本质是 autoload.php 加载了,但后续的 classmap 或 PSR-4 映射没覆盖到目标类。
- 用
var_dump(composer\Autoload\ClassLoader::getRegisteredLoaders())查看当前注册的 loader 实例,确认你的包路径是否在$loader->prefixesPsr4或$loader->classMap里 - 离线时别依赖
autoload-dev:测试类通常不在生产 autoload 里,composer install --no-dev会直接忽略它们 - 最简验证法:在入口脚本里加
echo file_get_contents('vendor/composer/autoload_classmap.php');,搜你要的类名,看是否在数组键里
autoload_static.php 和 autoload_classmap.php 是最新生成的,以及确认 PHP 进程没缓存旧的 opcode 或 loader 实例。路径、顺序、缓存,三个点漏一个,就白 dump 了。










