Path仓库与子模块本质不同:前者是Composer依赖加载机制,后者是Git源码组织方式;混用会导致依赖失效、覆盖修改或CI失败。

Path仓库和子模块根本不是一回事,混用会出事
Composer path 仓库是依赖加载机制,Git 子模块是源码组织方式——两者作用域、生命周期、更新逻辑完全不同。强行把它们塞进同一个工作流,大概率导致 composer install 找不到包、git submodule update 覆盖本地修改、或 CI 构建时路径失效。
典型翻车场景:
- 你用
git submodule add把packages/auth拉进主项目,又在主项目composer.json的repositories里配了{"type":"path","url":"packages/auth"}—— 表面上能装上,但下次git pull && git submodule update --remote可能重置子模块 HEAD,而 Composer 不感知这个变化,vendor/myorg/auth还指着旧 commit,类文件却已消失 - 子模块目录下没放合法的
composer.json(比如只写了{"name": "myorg/auth"}却漏了autoload),path仓库会静默跳过它,报Could not find package myorg/auth,但错误提示根本不提“子模块”或“autoload 缺失”
想本地联调又想 Git 管理源码?只用 Path 仓库,别碰子模块
真正稳定的做法是:把每个模块当成独立 Git 仓库维护,但开发阶段完全绕过 Git 克隆动作,直接用 path + symlink 加载本地目录。Git 仅用于版本控制,不参与运行时依赖解析。
实操要点:
使用约定式提交(Conventional Commits)从 Git 历史记录中生成结构化变更日志,支持多种格式、AI 增强型描述以及可自定义的范围……
- 所有模块仓库保持独立远程地址(如
git@git.example.com:myorg/auth.git),但开发时不git submodule add,而是把克隆好的目录放在../packages/auth这类固定位置 - 主项目
composer.json中repositories写相对路径:{"type":"path","url":"../packages/auth","options":{"symlink":true}} - 模块自己的
composer.json必须含完整 autoload 声明,例如:"autoload": {"psr-4": {"MyOrg\Auth\": "src/"}}(注意末尾不加斜杠) - 改完
../packages/auth/src/代码后,只执行composer update myorg/auth,不要git commit或git push—— 那是发布前才做的事
如果非要保留子模块结构,就得彻底放弃 Path 仓库
某些遗留项目强制要求子模块组织,那只能退回到传统 VCS 模式:删掉所有 path 配置,改用 "type": "vcs" 声明子模块所在 Git 地址。
这意味着:
- 主项目
composer.json的repositories改成:{"type":"vcs","url":"../packages/auth"}(注意仍是相对路径,且指向的是 Git 仓库根,不是composer.json文件) - 每次改子模块代码,必须先
git add && git commit && git push,再在主项目执行composer update myorg/auth—— 因为 Composer 此时是按 Git commit hash 拉取,不是读本地文件系统 - 子模块目录必须初始化好 Git,并有至少一次 commit,否则
vcs类型源会直接报错退出,不给任何提示 - CI 环境中,得确保子模块被
git submodule init && git submodule update正确检出,否则composer install会因找不到 Git 仓库而失败
最容易被忽略的权限与路径陷阱
Windows 用户启用 symlink 后仍看不到软链接,大概率是权限问题;macOS/Linux 上 ls -la 显示正常但 PHP 报 Class not found,往往是因为 PSR-4 命名空间和目录结构对不上。
验证链路是否通的最小闭环:
- 运行
composer show myorg/auth,确认输出里source字段显示path类型及正确路径 - 执行
ls -la vendor/myorg/auth,Linux/macOS 应看到-> ../packages/auth;Windows 用dir vendormyorguth看是否标为<SYMLINKD> - 手动检查
../packages/auth/composer.json中name是否和require里完全一致(大小写、vendor 名、分隔符全要对) - 用
composer dump-autoload -vvv观察是否扫描到了../packages/auth/src/下的文件 —— 如果没扫,八成是 PSR-4 的命名空间前缀或路径写错了

















