根本原因是Windows默认禁止跨盘符创建符号链接,即使管理员权限也会静默拒绝;必须将主项目与本地包置于同一盘符(如均放C:\dev\),且本地包composer.json含"options":{"symlink":true},repositories.url用相对路径(如"../my-pkg")。

为什么 Windows 上 composer require 的 path 仓库不生成 symlink?
根本不是 Composer 不支持,而是 Windows 默认禁止跨盘符创建符号链接(比如从 C:\project 指向 D:\my-pkg),哪怕你以管理员身份运行终端,系统策略仍会静默拒绝。
验证方式很简单:运行 ls -la vendor/vendor/name,如果看到的是普通文件夹而非 -> D:\my-pkg 这类指向,就说明 fallback 到了 copy 模式——你改本地代码,运行时加载的仍是 vendor 里的副本。
- 必须把本地包和主项目放在同一盘符下(例如都放
C:\dev\) - 确保本地包根目录有合法的
composer.json,且含"options": {"symlink": true} - 主项目
composer.json中repositories.url必须是相对路径(如"../my-pkg"),不能带盘符或/结尾
composer link 在跨盘符场景下为何无效?
composer link 命令本身不检查盘符一致性,但它依赖底层 mklink 或 ln -s。Windows 下若目标路径跨盘符,mklink /D 会直接失败,而 Composer 不捕获该错误,只默默回退为复制。
更隐蔽的问题是:即使你手动用管理员权限跑了 mklink /D vendor/vendor/name D:\my-pkg,PHP 的 realpath() 在某些 SAPI(如 Apache mod_php)中会因权限模型限制返回 false,导致 autoloader 加载失败且无提示。
- 不要对已安装包强行
composer link跨盘符路径 - 若必须跨盘符调试,改用
path仓库 +composer update,并接受它 fallback 到 copy 模式(此时需手动composer dump-autoload同步变更) - VS Code 或 PHPStorm 中开启「Synchronize files on save」可缓解 copy 模式下的双写问题
WSL 或 Docker 中挂载 Windows 盘符路径导致 symlink 失效
在 WSL 里访问 /mnt/c/ 下的项目,或 Docker 使用 -v $(pwd)/../my-pkg:/pkg 挂载,都会让 Linux 内核无法为 Windows NTFS 文件系统创建真实符号链接——ls -la 显示 ->,但 PHP is_link() 返回 false,Composer 自动加载器彻底忽略该路径。
这不是配置问题,是文件系统能力边界。WSL 2 默认禁用 metadata 支持,Docker volume 挂载也不透传 symlink 权限。
- 把项目移到 WSL 原生路径(如
~/projects/),再用ln -s创建到/mnt/c/的软链供 Windows 工具访问 - Docker 场景下,别在宿主机跑
composer install;应在Dockerfile中COPY源码后RUN composer install - 若必须共享源码,用
git clone或rsync同步,而非挂载整个目录
如何确认 symlink 是否真正生效?
别信 ls -la 的箭头显示,要验证 PHP 运行时是否真能解析它。最直接的方法是:在项目里写一行临时代码,然后 var_dump(realpath('vendor/vendor/name'));。
如果输出是绝对路径且指向你的本地包目录(如 C:\dev\my-pkg),说明成功;如果还是 C:\project\vendor\vendor\name,那它就是个普通文件夹,Composer 已 fallback。
- 运行
composer dump-autoload -v,观察输出里是否出现类似Adding PSR-4 autoload rule for App\ to C:\dev\my-pkg\src的行 - 打开
vendor/composer/autoload_psr4.php,搜索你的命名空间,确认映射路径是绝对路径且拼写与realpath()输出一致 - Windows 用户注意:路径分隔符在 PHP 里统一用
/,但realpath()可能返回\,不影响 autoload


















