必须用"type": "path"类型仓库才能让Composer识别Monorepo中本地子包;需在根composer.json的repositories中显式声明相对路径(如"packages/foo"),子包composer.json须含匹配的name和dev-main版本,否则Composer会错误地去Packagist查找。

Composer 的 repositories 配置必须用 path 类型才能读本地子包
Monorepo 里子包不在根目录(比如放在 packages/foo),默认 composer install 找不到它们。关键不是改 autoload,而是让 Composer 知道“这个包存在且就在本地”。只有 "type": "path" 的仓库支持从相对路径加载开发中的子包,packagist 或 vcs 类型都不行。
常见错误是直接在根 composer.json 里写 "require": {"myorg/foo": "dev-main"} 却不声明仓库——这时 Composer 会去 Packagist 搜,报 Could not find package myorg/foo。
- 在项目根
composer.json的repositories数组里加一条:
{
"type": "path",
"url": "packages/foo"
}
-
url是相对于根composer.json的路径,不能以/开头,也不能用../ - 子包自己的
composer.json必须有明确的name(如"myorg/foo")和version(开发中建议设为"dev-main"或"@dev")
path 仓库的 options 控制是否软链接、是否跳过稳定性检查
默认情况下,Composer 会对 path 类型仓库里的包做 symlink(符号链接),即安装后 vendor/myorg/foo 指向 packages/foo。这方便实时调试,但有时需要复制而非链接(比如部署到不支持 symlink 的环境)。
- 禁用软链接:加
"options": {"symlink": false},此时会完整拷贝文件 - 跳过版本稳定性检查(避免报
minimum-stability错误):加"options": {"versions": {"myorg/foo": "dev-main"}} - 如果子包
composer.json里写了"minimum-stability": "dev",根项目也得同步配,否则仍可能失败
子包 autoload 路径错位会导致类找不到,不是 Composer 安装问题
即使 composer install 成功、vendor/myorg/foo 也存在,运行时仍报 Class not found,大概率是子包自己的 autoload 配置没对齐实际目录结构。
- 假设子包
packages/foo/src/Helper.php,其composer.json中autoload应写:
"autoload": {
"psr-4": {
"MyOrg\Foo\": "src/"
}
}
-
"src/"是相对于子包自身根目录(即packages/foo)的路径,不是相对于项目根 - 运行
composer dump-autoload后检查vendor/composer/autoload_psr4.php,确认映射路径是否正确 - 如果子包用了
classmap,确保生成时工作目录是子包根,而不是项目根
CI/CD 里 path 仓库会被忽略,必须换策略
GitHub Actions、GitLab CI 默认不会把 packages/ 目录作为依赖上传,composer install 时 path 仓库指向的路径不存在,直接失败。
- CI 中应改用
"type": "vcs",指向子包所在 Git 分支(如https://github.com/myorg/repo.git),并配"reference": "main" - 或者用
composer config --global repositories.xxx动态覆盖,但需确保 CI 环境能访问对应路径(不推荐) - 更稳妥的做法:发布正式版到私有 Packagist(如 Satis 或 Private Packagist),CI 始终走标准流程
本地开发用 path 很方便,但它的路径依赖本质决定了它不该出现在共享环境配置里——这点容易被忽略,直到 CI 第一次挂掉才意识到。


















