composer install必须读composer.lock,因为它只按锁文件中写死的版本号、哈希值和url安装,确保本地、ci、线上环境vendor目录完全一致;删锁文件或git忽略它会导致隐式update、依赖不一致及运行时错误。

composer install 为什么必须读 composer.lock
因为 composer install 的唯一职责是复现一个已验证过的依赖状态。它不解析 composer.json 中的版本约束(比如 "monolog/monolog": "^3.0"),只按 composer.lock 里写死的版本号、哈希值、下载 URL 安装。这保证了:同一份代码在本地、CI、线上服务器装出来的 vendor 目录完全一致。
常见错误现象:
- 删掉
composer.lock后跑composer install,结果装出一堆新版本包 → 实际触发了隐式update行为,不是设计预期 - Git 忽略了
composer.lock,团队成员各自install得到不同版本 →Class not found或序列化行为差异等 runtime 错误由此而来
性能影响很直接:有锁文件时,install 几乎不联网、不跑依赖求解器,纯本地缓存命中,秒级完成。
composer update 为什么会改 composer.lock 并耗时很久
composer update 的核心动作是丢弃当前 composer.lock,重新执行一次完整的依赖求解(NP-hard 问题)。它会:
- 联网请求 Packagist API,查每个包满足
composer.json约束的最新可用版本 - 递归校验 PHP 版本、扩展、子依赖间的兼容性冲突
- 生成新的依赖组合,并把精确版本写回
composer.lock
典型耗时场景:50 个包的项目可能卡住两分钟;PHP 升级后若 config.platform.php 还锁着旧版,update 会直接失败。
慎用信号:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 加
--dry-run先看会动哪些包:composer update --dry-run - 升级单个包时,用
--with-dependencies控制联动范围:composer update phpunit/phpunit --with-dependencies - 永远不要在生产服务器或未测分支上直接跑
composer update
什么时候该用 install,什么时候非得用 update
这不是习惯问题,而是环境职责决定的刚性规则:
- 新人克隆项目后第一件事:必须
composer install,不是update—— 否则他拿到的symfony/http-kernel可能比你本地高一个小版本,而那个版本悄悄改了 Request 对象的构造逻辑 - CI/CD 流水线、Docker 构建、线上部署脚本里出现
composer update,等于把版本控制权交给网络延迟和镜像同步状态,凌晨告警大概率由此而起 - 只有三种合理使用
update的场景:
– 项目初始化,还没生成composer.lock
– 明确要升级某几个包(如修 CVE)
–composer.json刚被修改(如新增require),且你确认需要重算整个依赖树
补充一点:改了 composer.json 后只跑 composer install 是没用的,它不会感知变更 —— 因为它根本不读 composer.json 的约束字段。
生产环境部署必须加 --no-dev,但别以为加了就安全
composer install --no-dev 是生产环境标配,它跳过 require-dev 下的包(如 phpunit、phpstan),减小体积、加快安装。但它不改变根本逻辑:install 依然严格按 composer.lock 装,只是过滤掉 dev 包。
容易被忽略的关键点:
-
--no-dev对composer update也生效,但它仍然会重算全部依赖(包括 dev 包的约束),只是最后不装它们 —— 所以不能用update --no-dev替代install --no-dev - 如果
composer.lock里记录的某个包本身就有运行时对 dev 包的隐式依赖(比如通过 class_alias 或反射调用),--no-dev可能导致运行时报错,这种问题往往在部署后才暴露 - CI 构建时建议加
--prefer-dist --no-interaction,避免因交互提示或源码安装拖慢流程
真正稳的部署链路,是 Git 提交了更新后的 composer.lock,然后服务器上只跑 composer install --no-dev --prefer-dist —— 其他任何变体,都在增加不可控变量。










