composer加载本地包必须在根composer.json的repositories中配置type为"path"的索引数组,url为相对路径(如"packages/utils"),且require包名、子包name、symlink选项三者严格匹配,否则静默回退packagist。

根目录 composer.json 的 repositories 配置必须写对
Composer 不会自动扫描 packages/ 或 apps/ 目录下的子包,所有本地路径识别都依赖根目录 composer.json 中的 repositories 字段。配错一个字符,composer require myorg/utils 就会静默 fallback 到 Packagist 加载远程包,而不是你刚改的代码。
关键点:
-
repositories必须是索引数组(不能写成对象),每项形如{"type":"path","url":"packages/utils"} -
url是相对于根composer.json的路径,不能以./开头,也不能用绝对路径(协作必崩) - 不支持递归通配:
"packages/*"只匹配一级子目录,services/core/v2这种路径必须单独加一条 - 改完
repositories后,必须运行composer clear-cache,否则旧缓存可能让新路径失效
require 中的包名和版本必须严丝合缝
子包 composer.json 里的 name 字段(如 "myorg/utils")和根项目 require 中的键名必须逐字符一致:大小写、连字符、斜杠方向全部敏感。写成 "MyOrg/Utils" 或 "myorgutils" 都会导致加载失败。
版本约束也绝不能写语义化版本:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- ❌ 错误:
"myorg/utils": "^1.0"—— Composer 会跳过本地路径,去 Packagist 找已发布的 1.x - ✅ 正确:
"myorg/utils": "*@dev"或"myorg/utils": "@dev"或"myorg/utils": "dev-main" - 子包自己的
version字段可省略,Composer 完全不读它;真正起作用的是name和路径一致性
符号链接不是默认行为,得手动启用并验证
预期中 vendor/myorg/utils 应该是指向 packages/utils 的软链,但实际看到的是完整复制?说明 symlink 没生效,Composer 已退化为 copy 模式。
必须显式启用:
- 在
repositories条目中加"options": {"symlink": true} - Windows 用户需确认终端以管理员身份运行,或已开启「开发者模式」(否则
mklink被禁用) - Linux/macOS 若仍失败,检查
vendor/所在文件系统是否挂载了noexec或nosymfollow - 建好软链后,删掉
vendor/myorg/utils目录再跑一次composer install,是最稳妥的重同步方式
autoload-dev 和测试路径不会自动合并
子包的 autoload-dev(比如 tests/ 下的测试类)默认完全不生效,哪怕它自己 composer.json 写得再规范也没用。根项目运行 phpunit 时根本找不到这些测试类。
解决办法只有一条路:
- 在根项目
composer.json的autoload-dev里,显式加上子包的测试路径,例如:"Acme\Utils\Tests\": "packages/utils/tests/" - 加完后必须在根目录运行
composer dump-autoload,不是在子包目录下 - 如果子包要独立运行测试(如 CI 中单独验证),它自己也得有完整的
autoload-dev和require-dev,但根项目调用时仍需上面那条显式配置










