必须显式开启 symlink 选项,否则 Composer 默认复制文件;原因包括:path 类型仓库默认禁用软链以保障可重现性,Windows/Linux 权限不足会静默回退,且仅 Composer ≥2.2 支持该选项。

必须显式开启 symlink 选项,否则 Composer 默认复制文件,改本地代码完全不生效。
为什么 vendor 里不是符号链接?
Composer 对 path 类型仓库默认禁用软链,这是设计行为,不是 bug。它优先保障构建可重现性,而非开发便利性。即使你写了 "type": "path",只要没声明 "options": {"symlink": true},它就老老实实把整个目录拷进 vendor/。
- Windows 下若未以管理员身份运行终端、或 NTFS 禁用了创建符号链接策略,Composer 会静默 fallback 到 copy 模式
- Linux/macOS 需确保当前用户有权限执行
ln -s,否则也会退为复制 - Composer 版本必须 ≥ 2.2;1.x 完全不支持
symlink选项
怎么配才真正生效?
配置必须同时满足三处位置中至少一处显式启用 symlink,且执行 composer update(不是 install):
- 写在主项目
composer.json的repositories项里:{ "type": "path", "url": "../my-package", "options": { "symlink": true } } - 或写在本地包自己的
composer.json中(该配置对所有引用它的项目生效):"options": {"symlink": true} - 执行命令时加
--with-dependencies并指定包名:composer update myvendor/mypkg --with-dependencies
验证符号链接是否真建成了?
别只看 vendor/ 目录是否存在,要确认底层链接关系和 autoload 是否通:
- Linux/macOS:运行
readlink vendor/myvendor/mypkg,输出应为绝对路径,不是空 - Windows:运行
dir vendormyvendormypkg,看到“符号链接”字样或指向外部路径的提示 - 检查
composer.lock中对应包的source.type字段是否为"path"(不是"dist"或"zip") - 执行
php -r "echo class_exists('MyPackage\Helper') ? 'ok' : 'fail';",输出ok才说明 autoload 生效
最容易被忽略的是:改了本地包代码后,必须确认符号链接没被意外破坏——比如某次 composer update 因权限失败而悄悄 fallback 成复制,之后再也没人发现。建议把 readlink 或 dir 检查加入日常开发 checklist。


















