本地包必须用path类型仓库配合"*"约束,因Composer不解析本地路径的语义化版本,仅读取本地composer.json的version字段;^、~、=等写法均无效或报错。

必须用 path 类型仓库 + "*" 版本约束,其他写法都会失效或报错。Composer 不会从本地路径解析语义化版本,它只做符号链接挂载,版本实际由本地包的 composer.json 中 version 字段决定。
为什么 ^1.2.0 或 1.2.3 在本地包里不起作用
Composer 对 path 类型仓库完全跳过语义化版本解析流程。你写 "my-vendor/my-package": "^1.2.0",它既不会去匹配本地包的 version,也不会报错,而是静默忽略该约束,仍按本地 composer.json 里的 version 值安装,并可能附带 warning:Skipped tag v1.2.0, no composer.json found(如果本地没打 Git tag)。
-
^、~、=、@stable、dev-main全部无效 - 写死版本号(如
"1.2.3")会被当作远程包查找,直接报Could not find package - 真正起作用的只有
"*"—— 它触发 Composer 去读取本地包根目录下的composer.json的version字段
正确配置 path 仓库的三个硬性条件
缺一不可,错一个就 Could not find package:
-
repositories中type必须是"path",不能是"package"或"vcs" -
url必须是相对于项目根目录下composer.json的路径,支持../my-package、./packages/foo,不能是https://或绝对文件系统路径(如/home/user/my-package) - 本地包目录下必须有合法
composer.json,且其中name字段必须和主项目require中的包名**完全一致**(包括大小写、连字符、vendor 名)
执行后如何确认软链接已生效
别只看 vendor/ 目录是否存在,要验证底层链路是否打通:
- Linux/macOS:运行
readlink vendor/my-vendor/my-package,输出应为你的本地路径 - Windows:运行
dir vendormy-vendormy-package,若显示<symlinkd></symlinkd>或指向外部目录,则成功 - 测试 autoload:运行
php -r "echo class_exists('MyPackage\Helper') ? 'ok' : 'fail';",输出ok才说明命名空间加载正常 - 改本地包代码后立刻运行测试,结果应实时反映修改 —— 这是唯一可信的调试验证方式
最容易被忽略的是 Windows 上符号链接权限问题:默认禁用,需开启“开发者模式”或以管理员身份运行终端,否则 composer update 表面成功,实际 fallback 到 copy 模式,改代码不生效。另外,CI 环境常禁用 symlink,得显式加 "options": {"symlink": true} 到 repositories 条目里才可靠。


















