composer锁定版本必须同时满足:composer.json写三位纯数字版本(如"topthink/framework": "6.3.5")、composer.lock提交至git、所有环境运行composer install;缺一不可。

没有“限制版本”的命令,只有三个必须同时到位的动作:composer.json 写死纯数字版本、composer.lock 提交进 Git、所有环境跑 composer install。缺一个,版本就可能漂移。
怎么在 composer.json 里写才算真正锁死
必须用不含任何符号的三位完整语义化版本字符串,比如 "topthink/framework": "6.3.5"。写成 "^6.3"、"~6.3.0"、"6.3.*" 甚至 "6.3" 都不行——这些都会触发 Composer 的语义化升级逻辑。
-
composer require guzzlehttp/guzzle:7.5.0是对的;composer require guzzlehttp/guzzle:^7.5.0是错的(它允许 7.5.x 全系列) -
"dev-main"不算锁定,每次composer update都可能拉新提交;要固定某次,得写"dev-main#abc1234" - 分支名含斜杠(如
feature/login)需 URL 编码为feature%2Flogin,否则解析失败
为什么改了 composer.json 还是被升级了
不是约束没生效,而是操作链断在某个环节:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 改了
composer.json却没运行composer update vendor/package,composer.lock仍是旧快照 - 虽然更新了
composer.lock,但没git add composer.lock && git commit,别人拉代码后仍用旧 lock - 上线时误用
composer update而非composer install,导致重新解析依赖树 -
composer update --lock看似安全,其实会重写 lock 文件(比如标准化字段顺序、修正 hash),Git diff 仍会变
composer.lock 是快照,不是保险柜
composer.lock 记录的是当前安装状态,它不会阻止你手动运行 composer update。只要不加参数,它就会全量重算依赖并覆盖 lock。
- CI/CD 中建议加一道检查:
git status --porcelain composer.lock+git diff --exit-code composer.lock,确保 lock 没被意外修改 - 如果
composer.json里写了"config": { "platform": { "php": "8.2.10" } },而目标服务器是 PHP 8.1,composer install会直接失败,哪怕包版本完全一致 - 部署时可用
composer install --locked校验:它会检查 lock 中每个版本是否仍满足composer.json的约束,不满足就报错退出
最容易被忽略的点是:composer.lock 必须和 composer.json 的精确版本声明共存。只靠 lock 文件,一旦被删或被 CI 工具忽略(比如某些 GitHub Actions 默认不 checkout lock),就彻底失效;只靠 json 声明,又无法约束嵌套依赖的传递版本。两者必须咬合才真正可控。










