replace不是卸载命令,仅影响依赖解析;必须先composer remove旧包,再配置replace与conflict,并执行dump-autoload;provide仅声明契约兼容,不干预autoload;下游依赖未升级时replace无效。

replace不是卸载命令,它只影响依赖解析
你写 "replace": {"old-vendor/package": "*"},Composer 不会删文件、不改 autoload、不执行任何安装或卸载动作。它只是在依赖图计算阶段告诉 Composer:“这个包的功能,我(当前项目)已经提供了”。如果 old-vendor/package 仍明文写在 require 里,Composer 会坚持装它——replace 完全无效。
必须先手动 remove,再配 replace + conflict
常见错误是直接加 replace 就跑 composer install,结果报 Your requirements could not be resolved。真正可行的顺序只有这一种:
- 运行
composer remove old-vendor/package—— 这步不可跳过,否则旧包文件和 autoload 映射还在 - 在根项目的
composer.json中添加"replace": {"old-vendor/package": "*"} - 同时加上
"conflict": {"old-vendor/package": "*"}—— 否则下游依赖若悄悄拉入旧包,运行时会炸出Fatal error: Cannot declare class X - 运行
composer dump-autoload -o,确保新类映射生效
replace 和 provide 的关键区别
replace 是“我彻底替代你”,provide 是“我实现了你的契约但不取代你”。两者行为完全不同:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
-
replace会让 Composer 彻底忽略被替换包的 autoload、脚本、依赖树 —— 即使其他包 require 它,也不会装 -
provide只参与依赖判断,不干预 autoload;你得自己配置autoload或确保类已可用,否则照样Class not found - 想用自研缓存实现兼容 PSR-16?用
provide更安全;想把整个symfony/http-foundation替成内嵌版本?才轮到replace
下游依赖不升级,replace 就是纸老虎
就算你本地 clean 干净、replace 和 conflict 都配齐,只要某个已安装包(比如 some-tool)的 composer.json 里还写着 "require": {"old-vendor/package": "^2.0"},CI 或新机器上 composer install 就会重新拉下旧包。
查谁在拖后腿:composer depends old-vendor/package。输出非空,就得要么:
- 推动该包升级到支持新方案的版本
- 自己 fork 它,改掉
require字段 - 放弃
replace,改用repositories+ 强制require指向你的 fork
别信 composer.lock 里没旧包就万事大吉——lock 文件只固化当前解析结果,掩盖不了真实依赖关系。










