必须将 repositories 写在项目根 composer.json 最外层,与 require 并列;url 须为 ./ 或 ../ 开头的相对路径,指向含合法 composer.json 的目录;本地包 name 和版本需严格匹配,启用 symlink 并执行 dump-autoload 才能热更新。

直接在项目根目录的 composer.json 里加 repositories,否则 Composer 根本不会扫描你本地的代码目录。
repositories 必须写在项目根 composer.json 的顶层
Composer 只读取项目根目录下 composer.json 文件最外层的 repositories 字段。写在 require、autoload、config 或任何嵌套结构里,全部无效——不报错,也不提示,只是静默跳过。
- 错误示例:
"config": { "repositories": [...] }—— 完全不生效 - 错误示例:把
repositories写进本地包自己的composer.json—— 对主项目无意义 - 正确位置:和
require、autoload并列,同级,位于 JSON 最外层
url 必须是相对路径,且指向含合法 composer.json 的目录
url 不接受绝对路径、file://、~/、环境变量或末尾带斜杠的写法(如 "./my-pkg/")。它必须以 ./ 或 ../ 开头,终点是一个真实存在的目录,且该目录下有语法正确的 composer.json。
- ✅ 正确:
"url": "../my-local-package"、"url": "./packages/utils" - ❌ 错误:
"url": "/home/user/pkg"、"url": "file:///path/to/pkg"、"url": "~/pkg" - 验证方法:在项目根目录运行
ls -la ../my-local-package/composer.json(Linux/macOS)或dir ..\my-local-package\composer.json(Windows)
本地包的 name 和 require 版本必须逐字匹配
Composer 对 name 大小写、分隔符(只认 /)、vendor 名完全敏感。写错一个字符,composer require 就会报 Could not find package,且 composer show --all 里根本不会列出它。
- 主项目
require写的是"acme/utils": "dev-main",那本地包composer.json的name就只能是"acme/utils"(不能是"Acme/Utils"、"acme-utils") - 版本号必须用
dev-main这类分支别名,不能用"*"、"^1.0"或"@dev"—— 后者会让 Composer 回退到 Packagist 查找 - 若本地包还没
git init,建议在它的composer.json中显式加"version": "dev-main",否则 Composer 无法推断分支
改了代码不生效?大概率没启用 symlink 或没刷新 autoload
默认行为是复制(copy),不是链接。改了本地包代码,vendor/ 下的副本不会自动更新。
- 启用热更新:在
repositories条目中加"options": {"symlink": true} - Windows 用户必须以管理员身份运行终端,否则
symlink创建失败且无提示 - 改了本地包的
autoload映射(比如新增命名空间),必须在主项目根目录执行composer dump-autoload,否则新规则不加载 - 首次引入必须用
composer update acme/utils(带包名),install不重建链接
最容易被忽略的点是:本地包目录下没有 Git 仓库(至少一个 commit),或者 composer.json 里 name 字段漏了 vendor 部分(比如只写了 "utils"),这种情况下 Composer 会静默跳过整个路径,连 warning 都不给。验证是否真链接成功,别只看文件是否存在,而要看 vendor/acme/utils 是不是符号链接或 Junction。


















