composer.lock是依赖契约而非缓存,删除后运行install会引发环境不一致;cpu拉满卡死是sat求解器在依赖闭环中无限回溯,需用composer depends --tree或composer prohibits定位冲突源。

别删 composer.lock —— 它不是缓存,是契约;删了再 install 不是修复,是制造新问题。
为什么 composer install 卡住、CPU 拉满?
这不是网络慢或磁盘满,是依赖求解器在闭环约束里无限回溯。典型表现:终端无响应、php 进程吃光 CPU、内存持续上涨,且不报错。
- 运行
composer show -t --no-dev --ignore-platform-reqs,人工扫输出中反复出现的包名(如package-a → package-b → package-a) - 若树太深,加
| grep -E "package-a|package-b"快速过滤 - 重点查
require和require-dev是否对同一包写了冲突版本(如"symfony/console": "^5.4"和"symfony/console": "^6.2"并存) - 避免在
require-dev里写"dev-main"或"*"—— 它们会让求解器爆炸式搜索
composer why-not 输出一堆链,怎么快速定位卡点?
它输出的不是“谁拦你”,而是“所有拒绝理由链”。真正卡死的,往往在最后一行那个无法升降级的叶子节点。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 从最后一行倒着看:
root requires是起点,往上每行末尾的(required by ...)是追溯路径 - 如果某行结尾是
topthink/think-swoole,立刻去它 GitHub 查composer.json和 issue,确认是否支持目标 PHP 版本或目标包 - 比
why-not更快的命令是composer prohibits vendor/package:version,它直接列出所有冲突来源 - 注意
require-dev包也参与解析 ——phpunit/phpunit的约束可能把symfony/console卡死在 5.x
想更新一个包,又怕带崩整棵树?
用 composer update vendor/package --with-dependencies,不是 update 全量,也不是 require 模糊匹配。
- 必须显式写出包名,不带引号、不带
^或~(例如composer update monolog/monolog --with-dependencies) -
--with-dependencies是关键:它只升级该包及其直系依赖,不会动phpunit或其他无关项 - 如果提示 “Your requirements could not be resolved”,先查
composer show --platform—— 很可能是 PHP 版本或扩展不匹配,不是命令问题 - 升级后立刻
git diff composer.lock,确认只有预期包和其子依赖被改动
composer update --lock 是什么场景下该用的?
它是唯一安全的“只更新 lock 文件”方式:不升级包、不改 vendor、不触发网络请求,只刷新哈希与结构。
- 适用场景:你改了
composer.json里的platform、minimum-stability,或手动编辑过composer.lock导致 Git 合并冲突 - 执行后
git diff composer.lock应只显示元数据变动(如content-hash重算、packages数组重排),绝不会出现版本号变更 - 别把它和
composer install混用 ——install严格按 lock 装,update --lock只修 lock,二者目的完全不同 - 团队协作中拉新代码报错,大概率是别人提交了新
composer.json但没同步composer.lock,此时应先git checkout -- composer.lock恢复,再install
最易被忽略的一点:冲突常藏在 require-dev 里,而你只盯着 require 看。一个 phpunit 的旧约束,就能让整个 symfony 生态锁死在上一代 —— 它不报错,只卡住,等你主动去挖。










