是,大概率symlink未生效导致Composer静默fallback至copy模式;需验证ls -la vendor/name是否含->或Windows下dir是否显示,并确认主项目repositories中配置"options":{"symlink":true}、url为合法路径、name逐字节一致、本地包已git init且有commit、终端具备symlink权限。

本地包改了代码,vendor 里没变,是不是 symlink 没生效?
大概率是 symlink 创建失败,Composer 静默 fallback 到 copy 模式。它不会报错,但 ls -la vendor/acme/utils(macOS/Linux)或 dir vendor\acme\utils(Windows)看不到 -> 或 <symlinkd></symlinkd> 就说明没走符号链接。
必须同时满足这五点,symlink 才可能成功:
-
"options": {"symlink": true}显式写在主项目composer.json的repositories条目里,不能省略 -
url值必须是相对路径(如"../my-package")或绝对路径(如"/Users/me/my-package"),不能带file://或~ - 本地包
composer.json中的name字段(如"acme/utils")和主项目require中写的**逐字节一致**(大小写、斜杠方向都不能错) - 本地包目录已执行
git init且至少有一个commit;否则 Composer 直接拒绝 symlink - 终端有权限创建符号链接:macOS/Linux 看目录 sticky bit 和 group 写权限;Windows 需管理员身份或开启“开发者模式”
为什么 composer update acme/utils 后还是旧代码?
因为版本约束写错了。用 "*" 或 "^1.0" 这类宽松约束时,Composer 会优先查 Packagist,而不是你的本地 path 仓库。
正确做法只有两种:
- 本地包
composer.json中设"version": "dev-main",主项目require写"acme/utils": "dev-main"——这样切分支后composer update acme/utils才会触发 symlink 更新 - 更省事:主项目直接写
"acme/utils": "@dev",它强制走 path 源,不查 Packagist,也不依赖本地包的version字段
如果本地包目录被删了,composer install 会安静跳过,不报错也不装,容易误判为“更新成功”。验证前先 ls ../my-package 确认路径存在。
如何确认 symlink 是否真在工作?
别信 composer update 的输出,它从不告诉你用了 symlink 还是 copy。唯一可靠方式是看 vendor 下的实际文件系统结构:
- macOS/Linux:
ls -la vendor/acme/utils,输出中必须含-> ../my-package才算成功 - Windows:
dir vendor\acme\utils,看到<symlinkd></symlinkd>类型而非<dir></dir> - 改一行本地包代码,立刻在主项目里
var_dump或断点验证——这才是最终判决
注意:即使 symlink 成功,如果本地包没提交新 commit,某些 IDE 或调试器缓存可能让你误以为没更新。建议每次改完立刻 git add . && git commit -m "dev"。
config.symlinks: false 或全局关闭导致失效
主项目 composer.json 里如果写了 "config": {"symlinks": false},整个 symlink 机制就废了,不管 repositories 怎么配都无效。
还有几个隐形开关也得检查:
- 全局配置里有没有
composer config --global symlinks false?查一下:composer config --global | grep symlinks - 当前项目是否用了
composer install --no-symlinks?这个 flag 会覆盖所有配置 - CI/CD 流水线里是否默认加了
--no-symlinks?很多 GitHub Actions 的 composer action 默认关 symlink
最容易被忽略的是:Windows 上非管理员终端跑 composer update,哪怕其他条件全对,也会静默退回到 copy 模式。这时候 dir 看到的就是普通目录,不是符号链接。


















