因为composer path仓库默认复制而非符号链接,需在本地包composer.json中显式配置"options":{"symlink":true}并用composer update触发,且须验证ls -la vendor/pkg输出含->箭头。

为什么改了本地包代码,vendor里还是旧文件?
因为 Composer 的 path 仓库默认行为是复制(copy),不是符号链接(symlink)——这不是 bug,是设计使然,为保障 CI 构建可重现性。你看到 vendor 目录下是普通文件夹,说明 symlink 根本没生效,或创建失败后静默 fallback 到 copy 模式。
常见现象:composer update acme/utils 执行完,ls -la vendor/acme/utils 输出中没有 -> 箭头;Windows 上用 dir vendor\acme\utils 看不到“JUNCTION”或“快捷方式”字样。
- 必须显式启用 symlink:在本地包自己的
composer.json根级加"options": {"symlink": true}(主项目配置repositories里的options在新版中已不被优先读取) - Composer 版本需 ≥ 2.2;旧版本完全忽略该配置,且不报错
- Windows 用户必须以管理员身份运行终端,或已开启“开发者模式”,否则 symlink 创建失败且无提示
- Docker 场景需启动时加
--cap-add=SYS_ADMIN,且宿主机挂载目录需支持 symlink
怎么配 repositories 才能让 Composer “看见”你的本地包?
根本原则:require 字段只声明“我要谁”,repositories 才决定“去哪找”。如果 composer show --all | grep acme/utils 查不到包名,90% 是 repositories 配置无效。
-
url必须指向含合法composer.json的目录,不是文件,也不是 shell 当前路径;推荐相对路径,如"../my-utils"(末尾不能带/) - 本地包
composer.json中的name字段(如"acme/utils")必须与require中的字符串逐字一致:大小写、分隔符(仅限短横线-)、vendor 名全部对齐 - 版本约束只能用分支名,如
"dev-main"或"dev-develop";version字段在 path 源下被忽略 - 绝对路径在 Windows 上极易静默失败(盘符、反斜杠、空格都会中断),一律用相对路径
执行什么命令才能真正创建 symlink?
composer install 不会创建 symlink,它只按 composer.lock 还原依赖,完全跳过仓库类型解析和链接逻辑。必须用 update 触发完整流程。
- 首次引入:运行
composer update acme/utils(精确更新,避免波及其他包) - 已有依赖但 symlink 没建:先删掉
vendor/acme/utils,再执行composer update acme/utils - 后续修改本地包代码后:无需再
update——symlink 已存在,改源码即刻生效 - 如果改了本地包的 autoload 映射(如新增 PSR-4 命名空间),必须手动运行
composer dump-autoload,否则自动加载器找不到新类
怎么验证 symlink 是否真成功?
别信命令行输出,直接看文件系统。这是最容易被忽略也最关键的一步。
- Linux/macOS:运行
ls -la vendor/acme/utils,输出中必须有类似vendor/acme/utils -> ../../my-utils的箭头指向 - Windows:运行
dir vendor\acme\utils,应显示“JUNCTION”或“快捷方式”类型,而非“” - 打开
composer.lock,搜索该包,确认"source": { "type": "path" },而不是"type": "git" - Xdebug 断点失效?检查 IDE 中设置的路径映射是否指向本地包真实磁盘路径,而非 vendor 下的符号链接路径
composer update 成功就以为万事大吉,结果调试半天发现 vendor 里压根没连上源目录。











