微服务必须各自维护独立的composer.json和composer.lock,禁止共享vendor或共用配置;require仅含运行时依赖,require-dev限于开发工具,私有包须语义化版本+显式仓库声明,ci中强制校验镜像与lock一致性。

微服务必须各自维护 composer.json 和 composer.lock
不存在“统一依赖规范”这种全局配置——每个微服务都是独立部署单元,composer.json 和 composer.lock 必须按服务粒度存在、提交、验证。共用一份 composer.json 或共享 vendor/ 目录,本质还是单体,只是加了目录前缀。
常见翻车点:
- 把所有服务塞进一个 Git 仓库,靠
user-service/、order-service/目录区分 —— 这会导致composer install时路径错乱、autoload 映射失效 -
.gitignore里写了composer.lock—— 立即导致 CI 构建结果不可复现,本地能跑、测试环境 Class not found - CI 流程中没检查
composer.lock是否存在或是否被缓存覆盖 —— 某次构建用了旧 lock,装出已废弃的 dist URL,直接下载失败
require 和 require-dev 的边界不能模糊
运行时真正需要的包(如 guzzlehttp/guzzle、ext-pdo_pgsql、monolog/monolog)必须进 require;仅用于开发、测试、构建的工具(如 phpunit/phpunit、phpstan/phpstan、symfony/maker-bundle)必须进 require-dev。
漏掉 --no-dev 是高频事故源:
- Docker 构建时没加该参数,
symfony/debug-bundle被装入生产镜像,/_profiler暴露敏感信息 -
symfony/flex被误放require,CI 中 recipe 自动注入配置,污染生产环境启动流程 - 本地调试用的
roave/security-advisories放错了位置,它只做安装拦截,不该参与运行时
私有包必须走语义化版本 + 显式仓库声明
跨服务共享逻辑(如 DTO、认证工具、事件总线接口),不能靠 autoload.psr-4 映射到其他服务目录,而应发布为独立私有包,并在各服务中显式 require。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
关键实操细节:
- 私有包必须打语义化 tag(如
v1.2.0),不能长期依赖dev-main—— 否则 Satis 无法索引,CI 构建时反复 clone 失败 -
composer.json中repositories必须显式声明"packagist.org": {}键名(不是"packagist"或"default"),否则 Composer 2.9+ 会忽略镜像配置 - 若已有私有仓库(如内部 SDK),需合并而非覆盖:
"repositories": {"packagist.org": {}, "my-internal": {}} - 本地开发可用
"type": "path"临时替代,但上线前必须切回 VCS 地址,否则生产环境找不到包
CI 流程中必须强制执行可验证命令
靠文档约定或人工检查没用,所有关键行为必须固化进 CI 脚本并自动校验。
推荐做法:
- CI 开头执行
composer config --global --unset repos.packagist,防止某台构建机残留全局镜像干扰 - 加一行
composer config --list | grep -q "mirrors.aliyun"做健康检查,失败则中断构建 - 始终用
composer install --no-dev --optimize-autoloader --no-interaction,禁用update—— 后者会重写composer.lock,破坏可重现性 - 运行
composer install --dry-run观察日志中Downloading行 URL 是否含mirrors.aliyun.com等镜像域名,验证镜像策略是否生效
最易被忽略的一点:边缘节点执行 --optimize-autoloader 后仍报 Class not found,往往不是命令问题,而是没关掉自动发现机制 —— 若包未预生成 classmap,又用了动态 require_once,--classmap-authoritative 就会漏类。










