ci/cd 流水线必须用 composer install 且禁用 composer update,否则会导致依赖不一致、线上崩溃、环境行为差异等风险;应校验 lock 文件、缓存 composer 下载缓存而非 vendor、生产部署必加 --no-dev --optimize-autoloader --classmap-authoritative。

CI/CD 流水线里必须用 composer install,禁用 composer update —— 否则你部署的不是代码,是随机版本组合。
为什么 CI 里跑 composer update 是危险操作
它会重写 composer.lock,哪怕只是 monolog/monolog:2.10.0 → 2.10.1 这种 patch 升级,也可能触发未覆盖的边界逻辑。常见后果包括:
-
Class not found或Method not found错误,测试通过但线上崩溃 - 不同分支构建出的
vendor/实际内容不一致,导致“同一 commit 在不同环境行为不同” -
composer.lock被悄悄修改却未提交,后续开发者本地composer install行为不可预测
CI 不是做依赖决策的地方,它只负责“还原”——还原出和本地开发、生产环境完全一致的依赖树。
composer install 必须有 composer.lock 才能运行
没提交 composer.lock,composer install 会退化为 composer update 行为(并生成新 lock),这在生产服务器上极其危险。CI 脚本开头应加校验:
composer validate --strict
该命令会检查 composer.json 和 composer.lock 是否匹配。不匹配时直接失败,不能靠 --ignore-platform-reqs 强行绕过。
本地开发建议配 pre-commit 钩子:composer install --dry-run,提前发现 lock 过期或不一致。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
缓存 ~/.composer/cache,别缓存 vendor/
缓存 vendor/ 看起来快,实则危险:
- 不同 PHP 版本、不同扩展(如
ext-apcu开关)、甚至不同大小写敏感系统生成的 autoload 文件不兼容 - 会导致随机
Cannot declare class或include(): Failed opening错误
真正安全的缓存对象是 Composer 自己的下载缓存目录,它只存 zip/dist 包,跟环境完全解耦:
- GitHub Actions 示例:
path: ~/.composer/cache,key必须包含${{ hashFiles('**/composer.lock') }} - GitLab CI 中写
cache: paths: [~/.composer/cache],别写vendor/
缓存失效最常见原因:本地手动生成了新 composer.lock 但没提交,导致 key 不匹配,CI 每次走冷安装。
生产部署必须加 --no-dev --optimize-autoloader --classmap-authoritative
这三个参数不是可选项,是 autoload 性能的底线:
-
--no-dev:跳过require-dev,减小镜像体积、避免加载测试工具类 -
--optimize-autoloader:把 PSR-4 映射编译成静态数组,避免每次自动加载都执行file_exists()探测 -
--classmap-authoritative:告诉 Autoloader “不在 classmap 里的类,一律不存在”,彻底跳过文件系统查找
不加的话,PHP 每次自动加载都要遍历映射、试探路径,IO 开销大,还容易因符号链接、大小写或 opcache 失效漏类。
最容易被忽略的一点:离线部署时,composer.lock 一致 ≠ 代码字节一致。不同时间、不同镜像源下载的 dist 包 SHA256 可能不同,composer install 会校验失败。真要离线,传完整 vendor/ 比只传 lock 更可靠。










