composer update 不等于升级所有包,它默认只更新顶层依赖,子依赖保持最小兼容版本;需加 --with-all-dependencies 才连带升级全部子依赖。

别用 composer install 升级 vendor,它只还原,不升级;真要升级依赖,必须用 composer update,但得清楚它会重算整个依赖树、改写 composer.lock,且默认只升顶层包——子依赖可能卡旧版。
为什么 composer update 不等于“升级所有包”
默认执行 composer update 时,Composer 会重新解析 composer.json 中所有 require 条目,但对它们的子依赖(如 monolog/monolog 依赖的 psr/log)只做最小兼容更新,不会主动升到最新小版本。结果就是:你看到 monolog 升了,但 psr/log 还停在 1.2.0,运行时报 Class not found 或方法不存在。
- 想连带升级全部子依赖,必须加
--with-all-dependencies参数 - 只升级某一个包(如
composer update guzzlehttp/guzzle),它的间接依赖仍按原lock文件装,极易引发兼容断裂 - CI/CD 流水线里漏掉
--with-all-dependencies,不同机器产出的vendor/实际内容不一致
composer update 报 “Your requirements could not be resolved” 怎么办
这不是网络问题,而是约束冲突:当前 composer.json 的版本范围 + 已有 composer.lock 记录的旧版本 + 新可用包之间无法找到交集。常见于手动改过 composer.json 后没跑 update,又删了 vendor,再直接 install 失败后硬切 update。
- 先运行
composer validate,确认composer.json和composer.lock语法合法、结构匹配 - 如果
validate过,但update仍卡住,大概率是某个包已弃用或约束太紧(比如"php": ">=8.2.0"而本地是 8.1) - 临时绕过平台限制可加
--ignore-platform-req=php,但仅限调试,生产环境禁用 - 真要强解,用
composer update --lock强制生成新 lock(等价于从头算一次),但会丢失历史锁定语义
升级后 vendor/autoload.php 加载失败?检查路径和缓存
升级本身不改 autoload 路径逻辑,但如果你自定义过 config.vendor-dir 或设了 COMPOSER_VENDOR_DIR,update 会按新路径重建 autoload.php,而代码里若还写死 require 'vendor/autoload.php' 就必然失败。
- 确认
composer.json中config.vendor-dir值是否被意外覆盖或拼错 - 运行
composer dump-autoload -o强制重生成优化后的自动加载映射(尤其升级后类名变更或 PSR-4 规则调整) - 缓存损坏比 vendor 缺失更隐蔽:执行
composer clear-cache再重试,否则可能从~/.composer/cache读到损坏的 zip 包,报Failed to extract - IDE(如 PHPStorm)可能缓存旧 vendor 的类索引,需手动触发 “Reload project” 或清空 External Libraries
最常被忽略的一点:升级不是原子操作。composer update 修改 composer.lock 的同时,也隐式改变了所有依赖的哈希值、下载地址和安装顺序。哪怕只升一个 patch 版本,也可能因构建脚本变化导致 post-update-cmd 执行失败,进而让 vendor/bin 下的命令缺失——别只盯着报错行,要看完整输出末尾有没有 Script ... handling the post-update-cmd event returned with error code。











