Composer不能拆微服务,它只负责装包、加载类和锁版本;真正拆分依赖人对业务边界的判断及通信机制设计,每个微服务须有独立composer.json,禁止共用根文件,需配置私有仓库与认证,autoload路径和命名空间须精准无误,CI/CD中仅允许composer install --no-dev -o。

Composer 不能拆微服务,它只管装包、加载类、锁版本——真正拆服务靠的是人对业务边界的判断和通信机制设计。
composer.json 必须按服务粒度独立存在
每个微服务目录下都要有自己专属的 composer.json,不能共用一个根文件。否则 A 服务 require 的 monolog/monolog 和 B 服务 require 的 spatie/laravel-ray 会混在一起,构建时要么漏装,要么装错环境不兼容的扩展。
- 服务目录结构应为:
user-service/composer.json、order-service/composer.json,各自声明最小必要依赖 -
require里只放运行时必需项,比如slim/slim、guzzlehttp/guzzle;require-dev放测试工具,上线前用--no-dev过滤 - 避免在
user-service中requireorder-service的代码仓库——这不是依赖,是耦合,会导致部署失败或版本冲突
私有 DTO 包必须显式配置 repositories + auth.json
多个服务共享数据结构(如 UserDto、OrderEvent)时,得抽成私有 Composer 包,但 Composer 默认不认私有 Git 地址。不配 repositories 和认证,composer require 会直接报 Could not find package。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 在服务的
composer.json中添加:"repositories": [{"type": "vcs", "url": "https://git.example.com/php/dto-shared"}] - 项目根目录建
auth.json,内容为:{"http-basic": {"git.example.com": {"username": "token", "password": "pat_abc123"}}},CI 环境禁用 SSH URL - 安装时明确指定分支或版本别名:
composer require example/dto-shared:dev-main,不带:dev-main可能拉不到最新提交
autoload 配置错一个字符,运行时才报 Class not found
composer.json 里的 autoload 不会在 composer install 时报错,但一旦写错,服务启动或调用时立刻崩,错误信息里还找不到源头是哪个包。
- 命名空间末尾反斜杠必须双写为
\,JSON 中单个是转义符,写成"AppShared"会导致整段 autoload 被忽略 - 路径必须相对于包根目录,
"src/"不能写成"./src/"或"src"(少斜杠);若包实际结构是lib/ValueObjects/,就得配"App\ValueObjects\": "lib/ValueObjects/" - 用
composer dump-autoload -o生成优化映射,但首次调试建议先跑composer dump-autoload(不加-o),避免优化后错误提示更模糊
CI/CD 流程中只允许 composer install --no-dev -o
线上部署和 CI 流水线里执行 composer update 是高危操作。它会无视 composer.lock,重新解析依赖树,可能把 guzzlehttp/guzzle 从 v7.5 升到 v7.9——看似小版本,但某个中间件的 on_stats 回调签名已改,日志字段就丢了。
- 开发阶段才用
composer update,且每次执行后必须跑全量测试,确认无破坏性变更 - 所有环境(dev/staging/prod)都必须提交
composer.lock到 Git,它是依赖快照的唯一可信来源 - CI 脚本中应进入服务子目录再执行:
cd user-service && composer install --no-dev --optimize-autoloader,防止 vendor 污染其他服务
真正难的从来不是写 composer.json,而是定义清楚“用户”和“订单”之间哪部分该用 HTTP 调用、哪部分该用消息队列、哪些字段必须放进 DTO 包、哪些逻辑必须留在各自服务内——这些决策不会出现在 composer.lock 里,但决定了系统半年后还能不能顺利迭代。

















