conflicts 字段仅作声明性提示,不参与依赖求解——它不阻止安装、不触发冲突报错、不纳入 sat 求解器约束;所谓“冲突”实由 require 或 replace 引起。

composer.json 里的 conflicts 字段不参与依赖求解
Composer 的 conflicts 字段只是声明性提示,不是约束条件——它不会阻止安装,也不会触发版本冲突报错,更不会被纳入 SAT 求解器的约束集合。你看到的“冲突”往往来自 require 或 replace 字段的互斥版本范围,而不是 conflicts 本身。
常见误解是以为写上 "conflicts": {"monolog/monolog": " 就能拦住旧版 monolog 安装,实际效果是:即使 monolog/monolog 1.9.0 被其他包拉进来,Composer 也照装不误,顶多在 <code>composer validate 时警告一句 Warning: Package monolog/monolog (1.9.0) conflicts with your requirement,但 install/update 继续执行。
-
conflicts只在composer show、composer depends或 Packagist 页面展示,用于人工阅读和生态兼容性说明 - 真正起作用的是
require(必须满足)、replace(声明替代关系)、provide(声明能力) - 如果你发现某个包没被装上,别先查
conflicts,直接跑composer why-not vendor/package看真实阻断链
conflicts 和 replace 的行为差异必须分清
这两个字段常被混用,但语义和执行逻辑完全不同:replace 是主动接管,conflicts 是被动提醒。
例如 laravel/framework 声明 "replace": {"illuminate/support": "^11.0"},意味着当它被安装时,Composer 会把 illuminate/support 从依赖图中移除,并禁止再单独 require 同一版本范围;而如果只写 "conflicts": {"illuminate/support": "^11.0"},Illuminate 包仍可能通过其他路径(比如另一个依赖间接 require)进入图中,Composer 不会干预。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
replace改变依赖图结构,影响版本求解结果 -
conflicts不改图,也不影响 lock 文件生成 - 多个包同时声明
conflicts同一包,不会叠加或合并逻辑——它们彼此独立,各自只对自身生效
CI/CD 中误用 conflicts 导致上线失败的典型场景
有些团队在私有包里滥用 conflicts 来“强制排他”,结果在 CI 环境中因 vendor 缓存未清理、或 lock 文件未提交,导致本该被拦截的包意外装上,运行时报 Class not found 或方法不存在。
根本原因是:CI 执行 composer install 时,只要 composer.lock 里已有冲突包的记录(哪怕它被某 conflicts 声明过),Composer 就照装不误。只有当你本地跑 composer update 且该包不在 lock 中时,conflicts 才会在解析阶段被扫描到并发出 warning。
- 生产环境部署应依赖
composer.lock的确定性,而非conflicts的提示 - 若真要阻止某包安装,必须用
replace+ 显式require替代品,或通过repositories屏蔽源 - 所有
conflicts声明都应在composer validate --strict下测试,确认它没掩盖真正的require冲突
conflicts 字段唯一可靠用途:文档化与生态协作
它最实在的作用,是让 packagist.org 页面显示“Conflicts with”标签,或让 composer depends vendor/package 输出可读性更强的依赖上下文。比如一个废弃包声明 "conflicts": {"old-logger": "*"},下游用户执行 composer why old-logger 就能看到明确提示:“This package is replaced by new-logger and conflicts with old-logger。”
但要注意:这个提示只在命令行交互时出现,不会进入 PHP 运行时,也不会改变自动加载行为。
- 不要在
conflicts里写模糊版本如"*"或=1.0.0",Packagist 解析不稳定,部分版本号格式会导致字段被忽略 - 如果两个包互相
conflicts,Composer 不会报错,也不会做任何仲裁——它只按依赖图顺序处理,后解析的包胜出 - 真正需要“逻辑合并”的场景(比如多模块共用一套冲突规则),应抽成独立包,用
require引入,而不是靠conflicts字段拼接










