composer install 不升级依赖,它只按 composer.lock 安装精确版本;改 composer.json 中的 ^2.11 为 ^2.12 无效,必须运行 composer update monolog/monolog 重算依赖并更新 lock 文件,否则 install 始终还原旧版本。

Composer 不能靠改版本号符号来“升级依赖”,真正决定是否升级的是你执行的命令(composer install 还是 composer update),以及 composer.lock 是否存在且与 composer.json 同步。
为什么改了 composer.json 里的 ^2.11 到 ^2.12,composer install 却没反应
因为 composer install 完全忽略 composer.json 中的版本范围写法,它只照着 composer.lock 里记录的精确版本安装。哪怕你把 "monolog/monolog": "^2.11" 改成 "monolog/monolog": "^3.0",只要不运行 composer update,lock 文件里的 "2.11.0" 就不会变,install 也绝不会主动升级。
- 常见错误现象:
composer install后composer show monolog/monolog仍显示2.11.0,以为命令失效 - 真正该做的:改完
composer.json后,必须运行composer update monolog/monolog(或不带参数的update)来触发解析和重写 lock - 注意:如果
monolog/monolog是子依赖(没出现在require里),直接改根composer.json不起作用,得先把它加进require再锁
composer update 到底按什么规则选新版本
它不是“找最新版”,而是从当前已满足约束的所有兼容版本中,选语义化版本最高的那个——前提是该版本能被整个依赖图接受,且不违反 config.platform 或其他包的反向约束。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
"^2.11.0"允许升到2.x.x中任意版本,但绝不跨到3.0.0;而"~2.11"实际等价于">=2.11.0 ,连 <code>2.11.1都可能被跳过 - 如果另一个已装包要求
monolog/monolog: ^3.0,Composer 可能强制升到3.0.0,哪怕你本地composer.json写的是^2.11 - 运行
composer update --dry-run能提前看到它打算装哪些版本,比盲猜可靠得多 - 用
composer prohibits monolog/monolog:3.0.0可快速定位谁在阻止升级,比why-not更直接
如何安全地只升一个包,不连带动其他依赖
默认的 composer update vendor/package 仍可能升级它的子依赖(比如 psr/log),除非你显式控制传播范围。
- 想最小影响:加
--with-dependencies—— 它会升目标包 + 所有直系依赖,但不会深挖到间接依赖层 - 想彻底隔离:先确认当前子依赖版本,再在
composer.json里把它们也写死,例如"psr/log": "3.0.0",再跑update - 更稳妥的做法:用
composer update vendor/package-a vendor/package-b显式列出所有要更新的包,漏掉的就绝对不动 - 注意:如果某子依赖被多个包共用,且版本冲突,
--with-dependencies可能失败,这时必须手动调和composer.json约束
composer.lock 被改了但你没察觉,后果有多严重
它不是“缓存文件”,而是部署一致性的唯一凭证。Git 提交记录里一次无意识的 lock 变更,可能让 CI 构建出和本地完全不同的 vendor/ 目录。
- 典型表现:本地
phpunit是9.6.13,CI 报Class 'PHPUnit\Framework\TestCase' not found—— 因为 lock 里实际装的是10.0.0,接口已重构 - 检查手段:
git status composer.lock必须成为日常;CI 脚本开头加composer validate --strict拦住不一致提交 - 修复方式:不要手改 lock,用
composer update --lock重签(仅刷新哈希、URL 等元信息,不改版本);若 lock 已损坏,从 Git 恢复上一个干净版本再install - 最易被忽略的一点:即使你写了死版本
"2.11.0",只要composer.lock没提交、或被 CI 脚本误删,install就自动退化为update,所有“锁定”形同虚设

















