因为path类型仓库默认复制而非链接,需在本地包composer.json中配置"options": {"symlink": true}并用composer update触发;install不重建链接,且软链接生效需autoload映射、IDE路径和版本声明三者对齐。

为什么composer install不创建软链接
因为path类型仓库默认行为是复制(copy),不是链接(symlink)。Composer 这么设计是为了保证部署可重现性,但本地开发时这就成了障碍——改了../my-package的代码,vendor/里还是旧副本。
关键点在于:软链接不是靠主项目配置开启的,而是由**本地包自己的composer.json决定**。必须在本地包根目录的composer.json里显式加:
"options": { "symlink": true }
- Windows 用户必须以管理员权限运行终端,否则
mklink失败且无任何提示 - Linux/macOS 下无需提权,但要确认系统支持符号链接(基本都支持)
- Composer 2.2+ 才真正支持该
options字段;低于此版本会静默忽略 -
composer install永远不重建链接,必须用composer update vendor/name
composer link和path仓库软链接的区别
composer link是历史遗留命令,只对已安装包生效,本质是在vendor/下手动建软链接,但它不改composer.lock、不触发autoload刷新、也不校验name匹配,极易导致后续composer update把它覆盖掉。
而path仓库 + "options": {"symlink": true}是正统路径,全程走 Composer 解析流程:验证name、生成autoload映射、写入composer.lock记录为path源,稳定性高得多。
-
composer link适合临时验证一个已发布的包,比如快速试用某分支 -
path仓库适合长期模块开发,尤其当你要跑phpunit或调试post-install-cmd脚本时 - 两者不能混用:
composer link后又composer update,链接大概率被删
如何验证软链接是否真生效
别只看vendor/目录有没有文件,得确认它是不是指向你编辑的那个源目录。不同系统验证方式不同:
- Linux/macOS:
ls -la vendor/vendor/name,输出应含-> ../my-package - Windows(CMD):
dir vendorendor ame,看到“JUNCTION”字样才算成功 - 统一验证法:
php -r "echo (readlink('vendor/vendor/name') ?: 'not symlink');" - 再进一步验证 autoload:
php -r "echo class_exists('MyPackage\Helper') ? 'ok' : 'fail';",输出ok才说明命名空间加载通了
软链接失效的三个隐蔽原因
即使ls -la显示是链接,断点进不去、类找不到、修改不生效,往往卡在这三处:
-
autoload映射没更新:改了本地包的src/结构或composer.json里的psr-4配置后,必须手动composer dump-autoload,否则vendor/composer/autoload_psr4.php还是旧的 - IDE path mapping 指向了
vendor/下的链接路径,而不是你实际编辑的源目录——Xdebug 断点只认真实磁盘路径 - 本地包
composer.json里没写"version": "dev-main",而主项目require写了"dev-main",Composer 推断失败后 fallback 到 copy 模式,且不报错
最常被忽略的是 autoload 和 IDE mapping 的双重脱节:链接存在 ≠ 类能加载 ≠ 断点能停。三者必须同时对齐。


















