composer不支持monorepo,必须在根composer.json中显式配置path仓库并启用"options": {"symlink": true},否则vendor内为复制而非软链;需禁用packagist.org、确保repositories顺序靠前、包名大小写及路径严格匹配、版本用"@dev"、修改后清缓存。

Composer 本身不支持 Monorepo,所谓“单仓多包”全是靠根 composer.json 里手动配 repositories + path 类型硬凑出来的——错一个字段,本地改的代码就完全不会加载,而且不报错。
为什么 composer install 后 vendor/ 里不是符号链接?
预期是 vendor/myorg/http-client 指向 packages/http-client,结果却是完整复制一份?说明 symlink 没启用,Composer 已退化为 copy 模式。
- 必须在
repositories条目中显式加"options": {"symlink": true},不能依赖默认行为 - Windows 用户需确认终端以管理员身份运行,或已开启「开发者模式」(否则
mklink被禁用) - Linux/macOS 若仍失败,检查
vendor/所在文件系统是否挂载了noexec或nosymfollow - 软链建好后,删掉
vendor/myorg/http-client目录再跑一次composer install,是最稳妥的重同步方式
repositories 配置顺序和 packagist.org 冲突怎么办?
你写了 {"type":"path","url":"packages/http-client"},但 composer require myorg/http-client 还是去 Packagist 下载旧包——根本原因是默认源没禁用,且顺序不对。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
-
repositories数组必须把path条目放在最前面 - 必须显式禁用默认源:
{"packagist.org": false} - 否则哪怕路径、名字都对,只要
require里带"^1.0"这类语义化版本约束,Composer 就会跳过本地直接查远程 - 每次修改
repositories后,必须运行composer clear-cache,否则可能读旧缓存导致路径失效
子包 name 和根 require 键名怎么才算“完全一致”?
大小写、连字符、斜杠方向全部敏感:acme/utils ≠ Acme/Utils ≠ acmeutils。写错一个,Composer 就放弃本地路径,静默 fallback 到远程包。
- 子包
composer.json中必须有非空name字段,格式为vendor/name(如"myorg/http-client") - 根项目
require中的键名必须逐字符匹配,包括大小写和斜杠方向 -
require中不能写"myorg/http-client": "^1.0"—— path 包不参与版本解析,应统一用"*@dev"、"@dev"或"dev-main" - 子包之间互相依赖时,所有被依赖方也必须出现在根
repositories中,否则依赖树解析失败
子包的 autoload-dev 为啥不生效?
根项目跑 phpunit 找不到子包里的测试类,不是路径问题,是 Composer 根本没加载子包的 autoload-dev 配置。
- path 类型包的
autoload-dev默认不启用,哪怕子包自己的composer.json写得再全也没用 - 必须在根项目的
composer.json的autoload-dev里手动加上子包的测试路径,例如:"tests/MySdkTest.php": "packages/my-sdk/tests/" - 如果子包要独立运行测试(比如 CI 里单独验证),它自己也得有完整的
autoload-dev和require-dev,但根项目调用时仍需上面那条显式配置
最隐蔽的坑永远藏在大小写、路径相对性、symlink 权限和缓存这四点上——它们不报错,只悄悄加载远程旧代码,让你调试半天才发现改的根本没生效。










