必须满足四个硬性条件:主项目composer.json最外层repositories中正确声明type为"path"的仓库、本地包目录含合法composer.json、name字段与require逐字一致、本地包自身composer.json启用"options":{"symlink":true};缺一即静默失败。

能联动调试,但必须满足四个硬性条件:主项目声明path仓库、本地包有合法composer.json、name字段逐字一致、启用symlink;缺一不可,且错一个字符就静默失败。
主项目 composer.json 的 repositories 必须写对位置和格式
它不是加在 require 里,也不是塞进 config 字段,而是直接写在 composer.json 最外层的 repositories 数组中:
-
type必须是"path",写成"package"或漏掉会彻底失效 -
url必须是相对路径(如"../my-utils"),绝对路径("C:/work/my-utils")或带波浪线("~/my-utils")全部不认 -
url指向的是**含composer.json的目录**,不能以/结尾("../my-utils/"会失效) - 整个
repositories块不能嵌套在其他字段下,必须和require、autoload并列
本地包自己的 composer.json 必须合规且 name 严丝合缝
这是 90% 失败的根源——Composer 不报错,只默默跳过你的本地目录,转头去 Packagist 找包。
-
name字段必须和主项目require中写的**完全一致**:"acme/utils"≠"Acme/utils"≠"acme-utils" - 本地包目录下必须有 Git 仓库(至少执行过
git init && git add . && git commit -m "init"),否则dev-main这类分支版本无法识别 - 如果还没提交,可在本地包
composer.json里显式加"version": "dev-main"临时绕过 - 别用
"*"或"@dev"——它们会让 Composer 忽略 path 源,直连 Packagist
必须启用 symlink,否则改代码根本不会生效
默认行为在 Linux/macOS 是链接,在 Windows 是复制;而复制模式下,你改本地源码,vendor/ 里永远是旧文件。
- 在主项目
composer.json的对应repositories条目里加:"options": {"symlink": true} - Windows 用户必须以管理员身份运行终端,否则
symlink创建失败且无提示,静默 fallback 到 copy - 首次引入必须用
composer update acme/utils(不是install),因为install只读composer.lock,不重新解析仓库类型 - 验证是否真链接成功:
ls -la vendor/acme/utils(macOS/Linux)应看到->;dir vendor\acme\utils(Windows)应显示“JUNCTION”或“快捷方式”
改了 autoload 或新增类后 vendor/autoload.php 不认?
哪怕 symlink 已建好,只要本地包修改了 PSR-4 映射或新增了命名空间,主项目的自动加载器就不会自动感知。
- 必须手动刷新:进主项目根目录,执行
composer dump-autoload -o - 不加
-o也行,但加了会生成优化后的autoload_classmap.php,加载更快 - 这个步骤和
composer update无关,不执行就永远找不到新类
最常被忽略的是:本地包目录下没 git init,或者主项目 repositories 写在了 require 里面;这两个点一旦出错,Composer 既不报错也不警告,只会安静地装一个空包或从 Packagist 下载同名包——你得自己 ls -la vendor/ 看一眼才知道它根本没连上。


















