composer 不支持同一包多版本共存,因其自动加载机制全局唯一映射命名空间到路径,手动“shadowing”需重命名空间并隔离路径,但风险高;真正可行的是子进程隔离、接口适配或fork重命名私有仓库。

不支持,Composer 的自动加载机制天然排斥同一包多版本共存;所谓 “Shadowing” 并非 Composer 原生能力,而是开发者手动绕过限制的高风险操作,极易引发 Cannot declare class 或 Class not found 错误。
Composer autoload 为什么无法区分版本
PHP 的 autoloader 是全局注册的,Composer 生成的 vendor/autoload.php 只会为每个命名空间映射到一个物理路径。比如 MonologLogger 永远指向 vendor/monolog/monolog/src/ 下的某一个版本——哪怕你把 v1 和 v2 都拷进 vendor 目录,composer dump-autoload 也只保留最后解析出的那个版本的 PSR-4 映射。
- 类名和命名空间在 PHP 运行时是全局唯一的,重复定义直接 fatal error
-
replace、provide字段只能骗过依赖解析器,不能改变实际加载行为 - 修改
vendor/autoload.php手动加条件判断?下次dump-autoload就被覆盖
“Shadowing” 实际指什么(不是官方术语)
社区里说的 “shadowing”,通常指用 PSR-4 映射把旧版代码复制进项目目录,并重命名其命名空间,从而避开 vendor 下的自动加载冲突。这不是 Composer 的功能,而是你主动隔离加载路径的结果。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 把 v1 版本源码复制到
src/MyCompany/MonologLegacy/ - 在
composer.json中添加:"MyCompany\MonologLegacy\": "src/MyCompany/MonologLegacy/" - 手动修改所有类文件的
namespace声明(如从Monolog改为MyCompanyMonologLegacy) - 确保旧版代码里没有硬引用
Monolog*全局命名空间,否则运行时仍会尝试加载 vendor 版本
运行时手动加载(require_once + 独立 autoloader)的风险点
有人尝试把旧版包整个下载到 legacy-sdk/,再执行 require_once 'legacy-sdk/vendor/autoload.php'。这看似绕过 Composer,但隐患极多:
- 旧版包自身的依赖(如
psr/log)可能与主项目版本冲突,导致class_exists('PsrLogLoggerInterface')返回 false - 闭包封装不能完全隔离——一旦旧版代码触发了全局 autoloader 注册(比如调用了
ClassLoader::register()),就会污染主环境 -
autoload-dev里的映射不会自动失效;如果旧版测试类被业务代码硬 require,照样报错 - 无法用
composer install --no-dev控制,因为这是手动加载,不在 Composer 生命周期内
真正可行的边界在哪里
所有“双版本”方案都要求你放弃“让 Composer 统一管理”的幻想。关键不是怎么配 composer.json,而是怎么切割加载边界:
- 子进程隔离最干净:用
proc_open()调用独立 CLI 脚本,每个进程有自己完整的vendor/和autoload.php - 接口抽象 + 适配器比硬塞两个版本更可持续:定义
HttpClientInterface,写V1Adapter和V2Adapter,运行时注入 - fork + 重命名 + 私有仓库是唯一能进 CI/CD 的方案:改
name和autoload.namespace,让 Composer 认为它们是两个包
最容易被忽略的是:旧版代码是否依赖 composer/autoload_static.php 中的 classmap 或 files 加载方式——这类加载不走 PSR-4,无法靠命名空间隔离,必须逐行检查并重写。










