Composer monorepo 管理依赖 path 仓库“伪装”本地包,需严格匹配 name、autoload、repositories 和 options 配置,否则静默加载远程包或类找不到;修改子包后须删 vendor 目录再 install 才生效。

Composer 本身不支持 monorepo,所谓“管理”,其实是用 path 类型仓库把本地子目录“伪装”成远程包源——配对稍有偏差,就会静默加载 Packagist 上的同名包,而不是你刚改的代码。
为什么 composer install 不报错但类还是找不到
常见现象是 Class not found,文件路径、命名空间、autoload 都对,但就是不生效。根本原因不是自动加载没刷,而是 Composer 根本没加载你的子包。
- 子包目录下没有合法的
composer.json,或缺name字段(比如写成"name": "my-sdk"而不是全限定名"name": "acme/my-sdk") - 根项目
composer.json的require键写的是"my-sdk": "*@dev",但子包name是"acme/my-sdk"—— 名字必须一字不差 - 子包
composer.json没写autoload,或 PSR-4 映射路径指向了不存在的目录(比如"src/": "src/"但实际代码在lib/) -
repositories没写在根项目composer.json顶层,而是塞进了某个子包里,完全无效
path 仓库配置最容易漏掉的三个字段
type、url、options 这三者缺一不可,且顺序和值敏感:
-
"type": "path":不能写成"package"或"composer",否则无法指向未发布的本地代码 -
"url": "packages/my-sdk":必须是相对于根项目composer.json的路径,不能带../(除非你在子目录里执行composer install,但那已不是根上下文) -
"options": {"symlink": true}:不加这个,vendor/acme/my-sdk是复制出来的副本,改子包代码不会实时反映;加了才是符号链接,改即生效
测试类不被 phpunit 找到怎么办
子包的 tests/ 目录默认不会被根项目加载,因为 Composer 不合并子包的 autoload-dev。你得手动告诉根项目:“这些测试路径我也要扫”。
- 在根项目
composer.json的autoload-dev下显式追加子包测试路径,例如:"autoload-dev": { "psr-4": { "Acme\MySdk\Tests\": "packages/my-sdk/tests/" } } - 别指望子包自己的
autoload-dev自动生效——它只在子包作为独立项目运行时起作用 - 改完
autoload-dev后必须运行composer dump-autoload,否则映射不会更新
修改子包代码后 vendor 里还是旧文件
这是最常被误判的“缓存问题”。实际上不是缓存,是 Composer 默认跳过已安装的 path 包同步逻辑。
-
composer dump-autoload完全没用:它只重生成自动加载映射,不触碰 vendor 内容 -
composer update acme/my-sdk可能也不生效:必须加--with-dependencies,否则依赖图里没变化就直接跳过 - 最稳妥的做法是删掉
vendor/acme/my-sdk目录,再跑一次composer install,强制重建软链接
monorepo 下的 Composer 管理,本质是“人工维持映射一致性”:路径、名字、版本约束、autoload 规则,四者必须严丝合缝。任何一处小写、斜杠方向、多余空格,都会导致静默失败——而错误信号往往延迟出现在运行时,不是安装时。











