Composer不支持Monorepo,需用path类型仓库将本地目录伪装成包源;必须满足四条件:type为"path"、url为精确相对路径、子包name与require键完全一致、版本约束用"@dev"而非"^1.0"。

直接用 Composer 的 require + version 约束管理 Monorepo 模块,必然引发依赖冲突——不是配置没生效,而是本地 path 包被跳过,Composer 去 Packagist 找同名包了。
为什么 composer install 不报错但模块代码不加载
常见现象是 Class not found 或调用的永远是旧版本逻辑,根源不是 autoload 没刷,而是 Composer 根本没加载你本地写的模块。
- 子模块目录下缺少
composer.json,或name字段为空、格式错误(如写成"order"而非"myapp/order-module") - 根项目
composer.json的require键写的是"myapp/order-module": "^1.0"—— 这会强制 Composer 忽略本地path源,转去远程找已发布的 1.x 版本 -
repositories没写在根项目顶层,而是误塞进某个子模块的composer.json里,完全无效 - 路径写错:用了
"./modules/order"(带./)或绝对路径,协作时必崩;正确写法是"modules/order"(相对于根composer.json)
path 仓库必须同时满足的四个硬条件
缺一不可,错一个字符就退化为远程加载或静默失败:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
type必须是"path",不能是"package"或其他 -
url必须是精确相对路径,例如"modules/order";"modules/*"仅在 Composer 2.2+ 有效,且要求该路径下每个子目录都有合法composer.json - 子模块
composer.json中的name字段必须非空、全限定、与根项目require键**完全一致**(大小写、斜杠、连字符全部敏感) - 根项目
require中对应项的版本约束只能是"@dev"、"*"或"dev-main",绝不能含"^"、"~"或数字版本号
私有模块的 require 字段怎么写才不锁死下游
私有模块不是封闭沙盒,它的 require 是下游项目的硬性枷锁。写错就会让整个 Monorepo 升级卡死。
- 禁用钉死版本:
"monolog/monolog": "2.9.3"或"guzzlehttp/guzzle": "7.4.5"是雷区 - 改用语义化范围:
"guzzlehttp/guzzle": "^7.2 || ^8.0"(前提是代码真兼容) - 更稳妥的做法是只写
"guzzlehttp/guzzle": "^7.2",靠 CI 多 PHP 版本 + 多 Guzzle 版本测试兜底 -
conflict字段不能替代宽松require—— 它只拦截,不参与协商;replace是替身机制,不是兼容方案 - 运行
composer why-not时,必须进入私有模块目录(如cd modules/order)再执行,否则查不到它真实的约束源头
符号链接没生成?说明 symlink 已退化为 copy
预期中 vendor/myapp/order-module 应该是指向 modules/order 的软链,结果却是完整复制一份——这是最危险的信号,意味着开发时改代码不会实时生效。
- 先确认是否启用了
--prefer-source或全局 config 开启了 symlink:composer config --global prefer-stable false不影响 symlink 行为 - 检查系统权限:Linux/macOS 需要支持 symlink;Windows 启用开发者模式或以管理员运行 cmd
- 执行
composer clear-cache再重装,旧缓存可能导致路径识别失效 - 验证是否真走本地源:安装后看
vendor/myapp/order-module/composer.json是否是符号链接指向原路径,而不是独立副本
真正容易被忽略的点在于:所有子模块的 autoload 必须收敛到自身命名空间,且不能硬引用主项目类;repositories 顺序即优先级,多个 path 源并存时,靠前的会覆盖靠后的同名包;生产构建必须移除 repositories 并切换至私有 Packagist,否则部署环境会因路径不存在而失败。

















