composer install严格按composer.lock安装精确版本,确保环境一致;composer update则忽略lock、重算依赖并更新lock,仅用于开发阶段主动升级。

直接说结论:依赖管理不是“装上就完事”,而是要分场景控制版本粒度、隔离开发/生产环境、并主动干预解析冲突——否则composer update随时可能把项目拖进兼容性黑洞。
什么时候该用 composer install 而不是 composer update
关键区别不在命令字面,而在你手头有没有可靠的 composer.lock。如果团队协作或部署到生产环境,必须用 composer install;它只读取 lock 文件里的精确版本,跳过依赖树重新计算,确保所有机器安装完全一致的包组合。
- 本地开发刚拉下代码?先跑
composer install,别手欠敲update—— 否则你装的版本可能和 CI 或线上不一致 - CI 流水线里强制加
--no-interaction --no-dev --optimize-autoloader,避免交互卡住、误装 dev 包、加载慢 -
composer.lock必须提交进 Git,它是依赖事实的唯一权威来源;删了它再install,等同于重跑update
^ 和 ~ 版本约束的实际影响差异
它们不是“差不多”,而是语义上严格不同的升级边界。用错一个符号,可能让 composer update 升级出破坏性变更。
-
^2.3.4允许升到2.99.99,但绝不会到3.0.0—— 这是 SemVer 下“向后兼容”的默认假设 -
~2.3.4只允许补丁更新,即2.3.5、2.3.10,但不会升到2.4.0 - PHP 自身版本也建议用
^8.1而非*或8.*,避免意外引入 8.3+ 的弃用警告甚至报错 - 如果你依赖的包没严格遵守 SemVer(比如某些小众库把功能更新放在 PATCH 位),
^就不安全,宁可用~或锁定具体版本
如何安全地移除一个已安装的依赖
别手动删 composer.json 里的 require 行再跑 update —— 这会触发全量依赖重解析,可能连带升级其他包,引发意料外的 break。
- 用
composer remove vendor/package,它会自动从require和require-dev中剔除,并执行最小化更新 - 如果该包被其他依赖间接引用(比如 A → B → C),
remove会失败并提示冲突,这时得先查composer depends vendor/package看谁在依赖它 - 移除后记得检查
vendor/autoload.php是否还加载相关类,有些包注册了files类型自动加载,删包后残留调用会直接 fatal error
Symfony Flex 用户特别注意 recipe 生效条件
Flex 不是魔法,它只在特定条件下才自动写配置文件。很多“配置没生成”问题其实跟 Composer 本身无关,而是 Flex 的开关或上下文没对。
- 确认
symfony/flex已安装且不是dev-main分支:composer show symfony/flex - 检查是否禁用了 contrib recipes:
composer config --list | grep allow-contrib,返回空说明被关了 - recipe 默认只对稳定版生效;如果装的是
dev-master或alpha版,Flex 直接跳过,加@stable强制走稳定通道 - 生成的配置文件常含
when@prod或when@dev条件块,运行php bin/console debug:config framework前先确认APP_ENV值是否匹配
最易被忽略的一点:Composer 解析依赖时,require-dev 里的包也会参与版本约束求解。哪怕你只在测试中用 PHPUnit,它的版本要求也可能卡住主依赖升级 —— 所以 dev 包也要认真管,不能当“临时工”随便加。











