composer install从不生成依赖树,仅严格按composer.lock还原精确版本;依赖树由composer update通过sat求解器构建,lock缺失时install退化为update并报错。

composer install 从不生成依赖树
它只读取 composer.lock,不做任何解析、计算或决策。所谓“依赖树生成”,是 composer update 或首次运行 composer install 且无 lock 文件时才触发的行为。
常见错误现象:在 CI 环境中执行 composer install 报错 Your requirements could not be resolved —— 这说明 lock 文件缺失或损坏,install 被迫退化为 update 行为,开始尝试重新计算依赖树,结果失败。
-
composer install的输入只有composer.lock,输出是vendor/目录结构和vendor/autoload.php - 即使
composer.json里写的是"monolog/monolog": "^3.0",只要 lock 里记着2.10.3,install 就装2.10.3 - 改了
autoload或scripts字段?install完全无视,不影响任何行为
依赖树实际由 SAT 求解器在 update 阶段构建
composer update 才是真正构建依赖树的入口。它调用底层 Solver.php,用布尔可满足性(SAT)算法求解所有 require 关系与版本约束的交集。
这个过程不是“逐个安装再检查冲突”,而是把整个依赖网络建模成逻辑规则集,然后一次性推导出唯一可行解(或报冲突)。
- 每条
require条目 → 转为“请求规则” - 每个包的
composer.json中声明的依赖 → 转为“包规则” - 平台配置(如
config.platform.php)→ 参与兼容性判断,哪怕只改一行也会导致重算 - 求解失败时的错误信息如
Conclusion: don't install guzzlehttp/guzzle 7.8.1,本质是 SAT 推导出的反证结论
show --tree 输出的是 lock 解析结果,不是实时计算
composer show --tree 看起来像在“生成依赖树”,其实只是递归展开 composer.lock 里已固化的关系链。它不访问 Packagist,不运行求解器,也不校验约束是否仍成立。
这意味着:如果 lock 文件过期(比如某包已废弃但 lock 还留着),show --tree 依然能正常输出——但它展示的是历史快照,不是当前可安装状态。
- 输出中的缩进层级 =
lock中记录的require嵌套深度 - 不会显示 dev-only 包,除非加
--dev参数(仍只读 lock,不重算) - 若 lock 缺失,该命令直接报错:
Could not load package information, composer.lock is missing
为什么 lock 文件不能手动生成或编辑
composer.lock 不是配置文件,是带完整校验的二进制级契约。它包含每个包的 sha256、dist.url、source.reference 和子依赖的精确版本,缺一不可。
手动修改其中任意字段(比如改一个 version 字符串),会导致后续 install 校验失败并中断:
Invalid checksum for vendor/some/package.zip-
Package some/package has no installed version(因 hash 不匹配被跳过) - CI 构建失败时,第一反应不该是“重跑 install”,而应检查 lock 是否被 git ignore、是否被 IDE 自动格式化、是否混入 Windows 换行符
真正需要调整依赖关系时,必须走 composer update 或 composer require,让 Solver 重新输出合法 lock。











