CI/CD中必须用composer install而非update以确保构建可重现;需提交composer.lock、缓存~/.composer/cache、加--no-dev--optimize-autoloader--classmap-authoritative参数,并校验PHP版本与扩展、设置COMPOSER_MEMORY_LIMIT。

CI/CD 中必须用 composer install,禁用 composer update——否则依赖树不可控,线上出错时连回滚依据都没有。
为什么 CI 里 composer install 总失败
不是命令写错了,而是环境没对齐:
-
composer.lock没提交到 Git:CI 拉下来的代码是空的,composer install直接报错退出,不会自动生成 lock - PHP 版本不匹配:比如
composer.json要求"php": "^8.1",但 CI 使用的是 PHP 8.0,部分包会被跳过或静默失败 - 缺失关键扩展:Alpine 镜像默认不带
ext-zip或ext-openssl,composer install可能卡住、无输出、进程被 kill - 内存不足:
COMPOSER_MEMORY_LIMIT默认受限,解析依赖图时峰值高,报Killed或Allowed memory size exhausted
解决方法统一前置:export COMPOSER_MEMORY_LIMIT=-1,并在 CI 步骤中显式安装缺失扩展(如 apk add php81-zip)。
composer install 必须加的三个参数
生产部署不是“能跑就行”,这三个参数缺一不可:
立即学习“PHP免费学习笔记(深入)”;
-
--no-dev:排除require-dev中的包(如phpunit、symfony/debug-bundle),避免体积膨胀、安全风险,也防止运行时class_exists('PHPUnit\Framework\TestCase')直接 fatal -
--optimize-autoloader(或-o):把 PSR-4 映射编译成静态数组,跳过每次 autoload 的目录扫描 -
--classmap-authoritative:告诉 autoloader “不在 classmap 里的类,一律不存在”,彻底禁用file_exists()探测
漏掉任意一个,autoload 性能就瘸腿:没 --classmap-authoritative,开了 --optimize-autoloader 也没用;没 --no-dev,class_exists() 判断可能直接崩。
缓存该缓 vendor/ 还是 ~/.composer/cache
缓存 vendor/ 是常见误区,它会导致随机 autoload 失败:
-
vendor/包含环境敏感内容:不同 PHP 版本生成的autoload_static.php不兼容;opcache 或 apcu 编译产物混用会引发Cannot declare class -
~/.composer/cache只存 zip/dist 包和元数据,与 PHP 版本、扩展、OS 完全解耦,是唯一安全缓存目标 - GitHub Actions 示例 key 必须含
${{ hashFiles('**/composer.lock') }},否则 lock 更新后缓存不失效 - GitLab CI 写
cache: paths: [~/.composer/cache],别写vendor/——哪怕你看到 vendor 目录变大了,也不代表它该进缓存
缓存失效最常见原因:本地手动生成新 composer.lock 却没提交,导致 key 不匹配,CI 每次走冷安装。
CI 脚本开头必须做的三件事
光跑 composer install 不等于依赖就绪,这三步要前置:
- 运行
composer validate --strict:校验composer.json和composer.lock是否匹配,避免 lock 过期却没察觉 - 检查 PHP 版本与扩展:用
php -v和php -m | grep -E 'zip|pdo|openssl'快速确认基础能力 - 设置平台约束(可选但推荐):
composer config platform.php 8.1.25,防止本地开发用 8.2、CI 用 8.1 导致 autoload 生成异常
真正容易被忽略的是 --classmap-authoritative 和 --no-dev 的耦合性:它们不是独立优化项,而是一组行为契约——一旦代码里有未兜底的 dev 类存在性判断,漏掉任一参数都会在运行时炸开。



















