Composer只读取当前工作目录的composer.json,子目录文件默认被忽略;必须通过repositories配置path类型仓库、require中精确匹配name和版本、子包autoload正确声明三者协同,才能使子目录包被识别和加载。

子项目或多模块项目不能靠 Composer 自动识别或“统一管理”,必须显式声明每个子包为 path 类型仓库,并确保 name、autoload、路径三者严格对齐,否则必然出现类加载失败、版本静默降级或 composer install 无响应。
为什么子目录的 composer.json 总是被忽略
Composer 不扫描子目录,也不支持“多入口”模式。它只读取当前工作目录下的 composer.json,其他同名文件完全不参与解析。
- 把
module-a/composer.json放进子目录,然后在根目录运行composer install→ 它根本不会看那个文件 - 想让主项目用上
module-a,必须在主项目的composer.json的repositories里加一条"type": "path"配置,且url是相对于主项目根目录的路径(如"../module-a") -
url不能写成"module-a"或"./module-a",否则 Composer 会尝试从当前命令执行路径去解析,极易越界或报错
子包 name 和 autoload 必须唯一且精确匹配
多个子包若共用同一命名空间前缀(如都写 "App": "src/"),最后只有最后一个生效;name 字段大小写、连字符、vendor 名称任意一处不一致,就会触发 Could not find package。
- 子包
composer.json中的name必须是全限定格式,例如"myorg/user-service",不能是"user-service"或"myorg-user-service" - 主项目
require里写的包名必须与之完全一致,包括大小写:"myorg/user-service": "dev-main" -
autoload段必须限定到自身目录,例如"MyOrg\UserService": "src/",绝不能写成"MyOrg": "src/",否则会和别的子包冲突 - 验证方式:运行
composer dump-autoload -v,看输出中是否列出你期望的映射路径
本地开发用 path,上线前必须删掉或替换
type: "path" 是开发联调专用机制,CI/CD、Docker 构建、生产部署时路径不存在,直接失败。它不是临时方案,而是明确的阶段分界线。
- Windows 下默认不支持符号链接,需显式加
"options": {"symlink": false},否则安装卡住或静默失败 - Linux/macOS 容器环境若用户无
ln -s权限,Composer 会 fallback 到复制模式,改源码不生效 —— 此时要手动rm -rf vendor/myorg/user-service再重装 - 上线前必须删除整个
repositories块,改用 Git 地址或私有 Packagist,并确保已打语义化 tag(如v1.2.0),再提交composer.lock - 切记:
composer update myorg/user-service不会自动拉取本地修改,得加--prefer-source --with-dependencies
最易被忽略的一点:所有子包的 vendor-dir 必须保持默认(即不设),否则 autoload_static.php 生成逻辑会错乱,IDE 补全和 CLI 运行时行为不一致 —— 这个细节没有错误提示,但会在上线后某次 composer dump-autoload 后突然失效。


















