class not found 根本原因是 vendor/autoload.php 中硬编码的 dir 路径错位,导致 psr-4 映射指向错误目录;应清空容器中 vendor 后执行 composer install --no-plugins --no-scripts --no-autoloader,再运行 composer dump-autoload -o 重建当前环境路径映射。

vendor目录被复制后Class not found怎么办
直接复制vendor/到容器里却报Class not found,不是 autoload 没生成,而是vendor/composer/autoload_static.php里硬编码了源机的绝对路径,比如$vendorDir = '/home/dev/project/vendor'——容器里这路径根本不存在。
- 别手动改
autoload_static.php,它每次composer dump-autoload都会重写 - 正确做法:进容器后先清空
vendor/(哪怕它已存在),再跑composer install --no-plugins --no-scripts --no-autoloader - 最后必须补一句
composer dump-autoload -o,它会基于当前容器根路径重新生成静态映射 - 验证方式:
php -r "require 'vendor/autoload.php'; var_dump(class_exists('Monolog\Logger'));"输出bool(true)
composer.lock里platform字段引发容器启动失败
容器里PHP是8.2.10,但composer.lock顶部写的是"php": "8.2.12",composer install会直接退出并报Your requirements could not be resolved,连vendor/都不会碰。
- 用
composer check-platform-reqs快速定位缺失项,它比看错误日志快得多 - 临时方案:
composer install --ignore-platform-reqs能过,但得确认代码真没用到8.2.12新增的json_validate()之类特性 - 长期方案:在开发机统一PHP小版本,或在
composer.json里显式声明"config": {"platform": {"php": "8.2.10"}}再composer update --lock - 注意:
--ignore-platform-reqs不跳过扩展检查,ext-zip缺了照样失败
容器构建时vendor目录残留导致静默错版
Dockerfile里写了COPY vendor/ .,但没删旧vendor/,结果新旧包混在一起——composer install不报错,运行时却加载了老版本的symfony/http-foundation。
-
composer install默认不会清理已有vendor/,这是设计行为,不是bug - Dockerfile里必须加
RUN rm -rf vendor && composer install --no-dev --prefer-dist - 如果用多阶段构建,build阶段用
composer install --no-dev --optimize-autoloader,copy时只取vendor/和autoload.php,别带composer.lock进最终镜像 - CI里常漏掉
--no-dev,导致phpunit等dev包进生产镜像,增大攻击面
离线容器镜像里dist.url仍是https协议
你把vendor/打进了镜像,但composer.lock里某包的dist.url还是"https://api.github.com/...",容器启动时composer install仍会尝试联网校验,卡住或失败。
-
COMPOSER_DISABLE_NETWORK=1是硬开关,必须在docker run或ENTRYPOINT里设,不能只靠Dockerfile里的ENV - 更彻底的做法:构建前在开发机运行
composer install --no-dev --prefer-dist,确保所有包都走dist而非source,然后检查composer.lock里每个dist.type是否为zip - 若必须用
source(比如本地私有包),改用path仓库并配"options": {"symlink": false},否则容器里软链失效 - 别信“我关了网络就安全”,
curl -I https://repo.packagist.org在容器里跑一下,才是真实验证
php -v和php -m的结果,得跟composer.lock顶部的platform字段一个字符都不能差。











