composer install不创建软链接是因为它仅按composer.lock还原依赖,不触发重新解析;需运行composer update vendor/name重建链接,且本地包composer.json必须含"options":{"symlink":true}、路径合法、name字段与require完全一致。

为什么 composer install 不创建软链接,却静默复制文件
不是 Composer “没做”,而是它尝试创建 symlink 失败后自动 fallback 到 copy 模式,且不报错、不提示。你看到的 vendor/vendor/name 是普通目录,说明链接根本没建成功。
关键原因有三个:
- 本地包自己的
composer.json缺少"options": {"symlink": true}—— 这才是决定是否启用 symlink 的开关,主项目配symlinks: true只是辅助 - Windows 下未以管理员身份运行终端,或未开启“开发者模式”(
Enable developer mode) - Docker 容器启动时没加
--cap-add=SYS_ADMIN,或挂载方式不支持符号链接(如bind mount在某些宿主机上会丢 symlink 权限)
验证是否真用了链接:ls -la vendor/vendor/name(Linux/macOS)或 dir vendor\vendor\name(Windows),输出里必须含 -> 或 JUNCTION 才算成功。
Invalid target path for symlink 错误不是权限问题,是路径校验失败
这个报错明确指向路径格式不合法,和 Permission denied 或 Failed to create symbolic link 完全不同。Composer 在解析 url 字段时做了硬性校验:
- 路径不能含
~或$HOME,必须是绝对路径(如/home/user/my-pkg)或相对于主项目根目录的相对路径(如../my-pkg) -
url必须指向一个**真实存在的目录**,且该目录下必须有合法的composer.json(语法正确、无尾逗号、全双引号) - 该目录本身不能是符号链接(即
../my-pkg不能是软链,必须是真实目录) -
symlinks: true必须写在repositories对应的 path 仓库对象内,不能放在config段里
常见错误:把 "symlinks": true 放在 {"config": {...}} 里,结果 Composer 根本不读这行。
改了本地代码,为什么 vendor 里没更新
composer install 不会重建已有链接的目标路径,它只按 composer.lock 还原状态。即使你改了本地包的代码,只要没触发重新解析,vendor 里的 symlink 仍指向旧 commit 或旧文件树。
- 必须运行
composer update vendor/name(指定包名),才会重新走 path 解析流程、重建 symlink - 不要用
composer update无参数,它会重算全部依赖,慢且易引入意外变更 - 如果之前是 copy 模式装的,
update也不会自动切回 symlink —— 需先删掉vendor/和composer.lock,再跑composer install --prefer-source -
autoload映射不会随 symlink 自动刷新;改了本地包的psr-4声明后,要手动执行composer dump-autoload -o
最容易被忽略的 name 字段匹配细节
报错信息里从不提 name,但 90% 的 path 仓库失败都卡在这儿。Composer 要求本地包 composer.json 中的 name 字段与主项目 require 里写的字符串**逐字完全一致**:
- 大小写敏感:
"acme/utils"≠"Acme/utils"≠"acme/Utils" - 分隔符只能是短横线
-,不能是下划线_或点. - vendor 名必须对齐,比如主项目写
"myorg/my-tool": "*",本地包就不能写"my-org/my-tool" - 路径末尾不能加
/:"url": "../my-pkg/"会导致整个仓库被静默忽略
验证方法:运行 composer show --all | grep vendor/name,如果没输出,基本就是 name 或路径不匹配。











