Composer本地包必须用"*"约束,因path仓库不解析版本号,仅读取本地composer.json的version字段;写1.2.3等会被当远程包查找而报“Could not find package”。

Composer 不支持“虚拟包”这个概念,所谓“虚拟包”其实是误用术语;你真正想配的,是本地路径包(path repository),而它的版本约束只能写 *,其他任何写法都无效或引发错误。
为什么 composer require vendor/pkg:1.2.3 对本地包会失败
Composer 默认只从 Packagist 或 Git 仓库解析版本,它看到 1.2.3 就去远程查,根本不会扫描本地文件系统。结果就是报错:Could not find package vendor/pkg at version 1.2.3。这不是网络问题,是机制限制。
解决路径只有一条:先注册 path 类型仓库,再用 * 引用。
-
repositories中必须包含{"type": "path", "url": "./packages/my-pkg"},url是相对于项目根目录的路径,不能是 URL 或带file:// -
require里必须写"vendor/pkg": "*",不能写^1.2、~1.2.0、dev-main或1.2.3@stable - 本地包目录下必须有合法
composer.json,且其中name字段要和require中完全一致
* 约束到底怎么起作用
写 * 不是“装最新版”,而是告诉 Composer:“别查远程,直接读这个本地包自己的 composer.json 里的 version 字段”。这个字段值才是最终生效的版本号。
- 如果本地包
composer.json写着"version": "dev-main",那主项目里看到的就是dev-main - 如果写的是
"version": "2.1.0",那composer show vendor/pkg输出就是2.1.0,哪怕你在主项目里写了"*" - 这个
version字段还影响 autoloading 和依赖解析——比如它声明了"php": "^8.1",主项目 PHP 版本不满足就会报错
常见踩坑点:你以为在约束,其实被忽略了
这些写法看起来合理,但对 path 仓库完全无效,还会埋下维护隐患:
-
"vendor/pkg": "^2.1"→ Composer 静默忽略^,仍按本地version字段安装,但控制台会警告Skipped tag v2.1.0, no composer.json found(尤其当本地没打 Git tag) -
"vendor/pkg": "dev-main"→ 报错Could not resolve packages,path类型不支持分支标识 -
"vendor/pkg": "2.1.0"→ 直接当远程包处理,必然失败 - 把
url写成../packages/my-pkg或/full/path/to/pkg→ Windows 下可能因路径分隔符或权限失败,推荐统一用./packages/xxx
真正锁定本地包内容的方式,不是靠版本字符串,而是靠文件系统状态——改了代码就变了,删了文件就装不上。所以别在 require 里玩文字游戏,盯紧本地包自身的 composer.json 和实际文件结构。


















