composer install是唯一安全选择,因其严格按composer.lock安装精确版本、哈希及dist url,确保各环境vendor目录100%一致;而composer update会重解整个依赖图,易引入不兼容变更。

直接用 composer install,别碰 composer update 除非你真想改依赖树——它不只升级一个包,而是重新求解整个依赖图,极易引入不兼容变更。
为什么 composer install 是开发协作和上线部署的唯一安全选择
因为 composer install 完全忽略 composer.json 里的版本约束,只认 composer.lock 里记录的精确版本、哈希值和 dist URL。这意味着:
- 本地、CI、测试机、生产环境只要执行
composer install,装出来的 vendor 目录内容 100% 一致 - 即使某个包在 Packagist 上删了旧版本或改了下载地址,只要 lock 文件里存着原始 dist URL 和校验哈希,安装仍能成功
- 从 Composer 2.5 开始,如果
composer.lock缺少composer.json中声明的某个包,install会直接报错,不再静默跳过——这是对锁定机制的强化,不是 bug
反观 composer update,它会清空 lock 文件中所有已解析结果,重新走一遍依赖求解流程。哪怕你只改了一行 "monolog/monolog": "^3.5",它也可能把 symfony/polyfill-php81 从 v1.30 升到 v2.0,而后者要求 PHP 8.2+——你的 PHP 8.1 环境当场崩掉。
composer require 和 composer update vendor/package 的真实分工
添加新依赖必须用 composer require,而不是手动改 composer.json 再 install。原因很实在:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer require monolog/monolog:^3.0会自动写入require字段、触发 lock 文件更新、下载包、校验完整性——一步到位 - 手动编辑
composer.json后漏了个逗号,或用了"1.2.*"这种已被弃用的写法,composer install会直接失败并抛出 JSON 解析错误,排查成本远高于敲一条命令 - 想升级已有包?优先用
composer update monolog/monolog,它只重算该包及其子依赖,不会牵连guzzlehttp/guzzle或doctrine/dbal - 若需测试某包的新版兼容性,可用
composer update --with=monolog/monolog:^4.0(Composer 2.4+),临时覆盖约束,避免污染主 lock
区分 require 和 require-dev 不是“要不要装”,而是“能不能装”
线上部署时加 --no-dev 是硬性要求,但很多人错在划分逻辑上:
-
require里只能放运行时真正调用的类:比如stripe/stripe-php(支付网关)、league/flysystem(文件系统抽象)——没它们,index.php启动就报Class not found -
require-dev是纯工具链:如phpunit/phpunit、roave/security-advisories(它本身不提供任何类,只在install时做冲突拦截)、laravel/pint(代码格式检查) - 典型翻车点:
symfony/var-dumper被误放require,导致生产环境多装 2MB 且暴露dump()函数;doctrine/migrations漏进require-dev,上线后数据库迁移命令直接消失
验证方法很简单:在空目录下执行 composer install --no-dev && php -r "include 'vendor/autoload.php'; new \Doctrine\Migrations\Version\Version();",如果报错,说明它不该在 dev 里。
composer.lock 必须提交,且不能靠“记得”来维护
只要 composer.lock 没进 Git,或者被 .gitignore 拦截,项目就等于没锁住依赖——这不是隐患,是既定事实。
- 现象包括:CI 流水线构建失败,报错指向某依赖的私有方法已被移除;本地
var_dump()正常,测试环境同个对象json_encode()输出为空(因 ext-json 版本浮动,而 lock 文件里没固化 platform 配置) - lock 文件和 json 文件必须语义匹配:比如
composer.json的"config": {"platform": {"php": "8.1.0"}},lock 文件里"platform": {"php": "8.1.0"}也得一致,否则install可能选错包 - 长期未更新的项目,dist URL 可能失效(Packagist 下架旧版),此时用
composer update --lock可仅刷新元数据,不升级包本身,适合紧急修复
最易被忽略的一点:团队里有人执行了 composer update 却没提交新的 composer.lock,其他人 composer install 实际装的是旧 lock 里的版本——这种“伪一致”比明显报错更危险,问题往往在线上才暴露。










