path-repository不能用相对路径因解析基于项目根目录而非composer.json位置,须用绝对路径或./开头的根相对路径;联动开发需确保path包含.git、主项目启用dev稳定性、version设为dev-main等。

path-repository 为什么不能直接写相对路径
因为 composer.json 中的 path 类型仓库路径,是相对于当前项目根目录解析的,不是相对于 composer.json 文件位置。如果你在子目录里执行 composer install,或者用 CI 工具切换工作目录,相对路径会失效——它压根不支持 ../my-package 这种写法,一写就报 Source path ".../my-package" does not exist。
实操建议:
- 所有
path值必须是绝对路径,或以./开头的、从项目根出发的路径(如./packages/my-package) - 避免跨 Git 仓库软链接:Composer 不会自动跟踪 symlink 目标是否已提交或更新,容易出现本地有改动但
composer update没感知 - 如果包本身有
autoload配置,确保它的psr-4映射路径与实际文件结构一致,否则类找不到
如何让 path-repository 真正“联动”开发
所谓联动,是指改了本地包代码,主项目立刻生效,不用反复 composer update。这依赖 Composer 的“符号链接安装”行为,但默认只在满足条件时触发。
实操建议:
- 主项目的
composer.json必须启用prefer-stable: false和minimum-stability: "dev",否则 Composer 会跳过本地 path 包,去拉 dist 包 - path 包的
composer.json中version字段要设为dev-main或dev-develop,不能是1.0.0这类稳定版号,否则会被当成已发布版本忽略 - 运行
composer require vendor/name:dev-main --no-update后再composer update vendor/name,强制走 symlink 而非 copy - 验证是否成功:检查
vendor/vendor/name是否是 symlink(Linux/macOS)或 junction(Windows),而不是复制出来的文件夹
常见错误:require 后没生成 symlink,还是 copy 了一份
现象是改了 path 包里的代码,主项目 var_dump 却没变;ls -l vendor/xxx 显示是普通目录,不是链接。根本原因是 Composer 认为这个包“可安装为 dist”,于是跳过了 symlink 逻辑。
排查和修复步骤:
- 运行
composer show vendor/name,看输出里有没有source: path /xxx/yyy—— 如果显示dist:且带 zip url,说明没走 path 模式 - 检查 path 包根目录下是否有
.git文件夹:没有的话,Composer 默认 fallback 到 dist 安装;加一个空.git目录(哪怕没 commit)就能强制走 source 模式 - 确认主项目
config段没设置"preferred-install": {"*": "dist"},这个配置会全局压制 symlink - 删掉
vendor和composer.lock,重新composer install
Windows 下 junction 替代 symlink 的兼容性注意点
Windows 默认不支持 mklink 创建 symlink(需要管理员权限或开启开发者模式),Composer 会退而求其次建 junction,但它有硬限制:目标路径不能跨盘符,也不能指向网络路径。
实操建议:
- 把主项目和 path 包放在同一磁盘(比如都在
C:\work\下),否则 junction 创建失败,Composer 会静默回退到 copy - 如果遇到
Could not create junction错误,先手动用管理员权限运行:mklink /j C:\path\to\vendor\vendor\name C:\path\to\your\package,再跑composer install - PHP
realpath()在 junction 下可能返回原始路径而非链接路径,调试时别全信__DIR__输出,用readlink()(Linux/macOS)或fsutil reparsepoint query(Windows)确认真实指向
.git 目录,以及主项目 lock 文件里残留了旧的 dist 引用——这两处一错,联动就断了,而且错误不报在表面。









