唯一可行方式是用 repositories 声明 path 类型仓库;需在主项目 composer.json 中配置 repositories 块,指定本地包路径及 name 一致的包名,并启用 "symlink": true 实现实时生效,生产环境必须移除该配置。

用 repositories 声明 path 类型仓库是唯一可行方式
Composer 不会自动扫描项目外的目录,本地包必须显式“注册”才能被识别。靠 composer require 直接输路径或改 autoload 都无效——它只管自动加载,不管包来源。
正确做法是在主项目的 composer.json 里加 repositories 块:
{
"repositories": [
{
"type": "path",
"url": "../my-utils"
}
],
"require": {
"acme/utils": "*"
}
}
-
url必须是相对路径(如../my-utils)或绝对路径(Windows 要带盘符,如C:/dev/my-utils) - 目标目录下必须存在合法的
composer.json,且其中"name"字段(如"acme/utils")要和require里完全一致 -
"*"版本会匹配包内version或dev-main等分支别名,但不能写成dev-master(除非包里真有该别名)
symlink: true 是开发模式的核心开关
默认情况下,Composer 会把本地包复制进 vendor/,改源码不会生效。要实现“改即生效”,必须启用符号链接。
在 repositories 配置中加入 options:
{
"type": "path",
"url": "../my-utils",
"options": {
"symlink": true
}
}
- Linux/macOS 下无需额外权限;Windows 需以管理员身份运行终端,或开启“开发者模式”
- 符号链接指向的是整个包目录,不是单个文件,所以
src/、tests/、composer.json全部实时可见 - 一旦启用
symlink,就不要再手动删vendor/acme/utils—— 它是个链接,删了就断了
本地包的 composer.json 必须满足最小契约
本地包不是普通目录,它得是一个能被 Composer 解析的“包”。最简配置至少包含三要素:
{
"name": "acme/utils",
"type": "library",
"autoload": {
"psr-4": {
"Acme\Utils\": "src/"
}
}
}
-
name必须与主项目require中的包名严格一致,大小写、斜杠方向都不能错 -
autoload推荐用psr-4,路径映射要真实存在(比如src/目录下真有Acme/Utils/Helper.php) - 不需要写
require或autoload-dev,除非你真依赖别的包或想跑测试 - 不要加
version字段——本地开发用分支别名(如dev-main)更可靠
生产环境必须彻底移除 repositories 配置
"type": "path" 是纯开发特性,进不了生产。CI/CD 流水线或部署机上若残留该配置,composer install 会直接失败,报 Could not find package acme/utils,不是网络问题,是路径根本不存在。
- 上线前必须从
composer.json中整块删掉repositories字段 - 推荐用环境隔离:开发用
composer.json,生产用composer.prod.json,通过COMPOSER=composer.prod.json composer install显式指定 - CI 脚本里加一道检查:
grep -q '"type":"path"' composer.json && exit 1,防误提交
真正麻烦的不是配置本身,而是路径有效性依赖开发机的本地目录结构——这东西没法跨环境迁移,也没法做版本快照。只要记住:path 仓库只活在你自己的终端里,它不该出现在任何 git commit、CI 日志或服务器配置中。


















