真正锁定依赖需三步:一是在composer.json中用纯数字版本号如"monolog/monolog": "2.9.1";二是将composer.lock提交至git;三是在ci中使用composer install --locked校验。

直接写死版本号才是真锁定,其他方式都只是临时绕行或表面控制。
composer.json 里怎么写才算真正冻结一个包
必须用纯数字、无任何前缀后缀的写法:"monolog/monolog": "2.9.1"。带 ^、~、*、dev-main as 2.9.1 的写法都不算锁定——它们会在下次 composer update 时被重新解析,可能升级到新版本。
-
"2.9"不推荐:某些 Composer 版本会自动补成"2.9.0",但不保证一致,别赌 -
"2.9.*"是通配符,允许安装2.9.999,不是锁定 - 改完
composer.json后,必须立刻执行composer update monolog/monolog,否则composer.lock里还是旧值或范围值 - 如果该包是子依赖(没出现在
require里),仅改 root 的require没用,得靠replace或conflict干预整个依赖图
为什么只靠 composer.lock 不够安全
composer.lock 是快照,不是契约。它只在 composer install 时生效,一旦被删、被覆盖、或 CI 流水线没拉到它(比如 GitHub Actions 默认只 checkout 代码),composer install 就会退化成按 composer.json 重新解析——这时如果里面写的还是 "^2.8",就可能装上 2.12.0。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须把
composer.lock提交进 Git,且不能加进.gitignore - CI/CD 构建时要用
composer install --no-dev --no-interaction,绝不用update - 上线前加一层校验:
composer install --locked,它会严格比对composer.lock中每个包是否仍满足composer.json的约束,不满足直接失败 - 某些插件(如 hirak/prestissimo)或新版 Composer(2.5+)会在
--lock时校验 hash 并修正字段格式,导致 diff 出现无关变更
临时跳过某个包更新的命令是否可靠
composer update --ignore=monolog/monolog 只在 Composer 2.2+ 生效,且它不改变依赖解析逻辑——被忽略的包若被其他包强依赖新版本,仍可能间接升级,所以不是“绝对冻结”。
- 低版本 Composer 不支持
--ignore,强行使用会报错Unrecognized option "--ignore" - 想只更新其他包,最稳妥的方式是显式列出要更新的包:
composer update laravel/framework symfony/console,不写monolog/monolog -
composer update --dry-run先看哪些包会被升,确认无误再执行 - 别信
composer config --no-updates这类伪配置,它不生效
replace 和 conflict 是最后防线
当某个包和当前项目存在兼容性冲突,或者你用了定制分支,需要从依赖树里“逻辑移除”原包时,replace 和 conflict 是更底层的控制手段。
-
"replace": {"monolog/monolog": "*"}:声明你已提供同名包的全部功能,Composer 就不会再装它(也不会检查其依赖) -
"conflict": {"monolog/monolog": ">=3.0.0"}:明确禁止某范围版本,update时若解析出该版本会直接报错退出 - 这两个字段都写在
composer.json的根级,不是require下面 -
replace不影响 autoloading,但你要确保自己提供的代码能真正替代原包行为,否则运行时报Class not found
真正锁定的关键动作只有三个:写死版本号、提交 composer.lock、CI 用 --locked 校验。漏掉任意一个,所谓“冻结”就只是心理安慰。










