github actions 中 composer install 慢或失败主因是环境配置与缓存策略错误:需用 setup-php 显式指定 php 版本及 zip/mbstring/xml 等扩展,缓存 ~/.composer/cache(key 含 php 版本和 composer.lock 哈希),并强制使用 --no-interaction --prefer-dist --optimize-autoloader --no-dev 参数;未提交 composer.lock 或私有包 token 未正确注入 auth.json 亦会导致报错。

GitHub Actions 里 composer install 慢或失败,90% 是环境配置和缓存策略不对,不是 Composer 本身的问题。
为什么 composer install 总是重装、超时或报错 platform constraint
根本原因在于 CI 容器每次都是干净的:没有 PHP 扩展、没启用 zip/mbstring/xml、PHP 版本和 composer.json 中 "php": "^8.2" 不匹配,或者 composer.lock 文件缺失或未提交。这些都会导致 composer install 直接退出,连缓存都来不及用。
- 必须先用
actions/checkout@v4拉下代码,确保composer.lock在工作目录 - 必须用
shivammathur/setup-php@v2显式指定php-version,不能依赖系统默认 PHP -
extensions参数要写全:至少包括zip, mbstring, xml, curl, json;若项目用pdo_mysql或redis,也得加进去 - 不提交
composer.lock就等于放弃依赖一致性,CI 会重新解析整个依赖树,极易失败
缓存 ~/.composer/cache 比缓存 vendor/ 更关键
很多人只缓存 ./vendor,结果发现构建时间没降多少——因为下载 ZIP 包仍占大头。真正该优先缓存的是 Composer 自己的全局缓存目录 ~/.composer/cache,它存着所有已下载的 dist 包、元数据和 lock 解析结果。
- 缓存路径必须写成
~/.composer/cache(不是.composer/cache或composer/cache) - 缓存 key 要包含
composer.lock哈希:${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - 如果用了不同 PHP 版本(比如 matrix 测试),key 还得加上
${{ matrix.php-version }},否则 8.1 和 8.2 共用缓存会出错 - 别用
actions/cache@v4缓存./vendor后再跑composer install——应该先 restore,命中则跳过 install;未命中才执行
composer install 必须带的参数不是可选,是强制
CI 环境没有交互终端、不跑测试、不调试源码,composer install 的默认行为在 CI 下全是坑。
-
--no-interaction:防止卡在 “Do you trust this repository?” 或认证 prompt,超时失败 -
--prefer-dist:强制走 ZIP 包而非git clone,尤其对私有 GitHub repo,在配好git config --global url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/"后依然生效 -
--optimize-autoloader:生成vendor/autoload_classmap.php,后续 PHPUnit 或 HTTP 请求阶段类加载快得多 -
--no-dev:除非你要跑测试,否则 dev 依赖(如 phpunit、phpcs)纯属拖慢构建、污染缓存
私有包认证不是“加个 token”就完事
报 Could not fetch https://.../package.zip 或 401 Unauthorized,不是 token 没传,而是没让 Composer 或 Git 知道怎么用它。
- GitHub Packages 场景:用
shivammathur/setup-php@v2的composer-auth: true参数,它会自动把GITHUB_TOKEN写进~/.composer/auth.json - 私有 GitHub repo 作为依赖:必须改
composer.json里的 URL 为 HTTPS(不是git@github.com:),再加一步git config替换域名前缀 - GitLab 或自建 Satis:需提前用
composer config生成auth.json,通过actions/upload-artifact或env注入,绝不能硬编码 token - 别漏掉
--no-interaction:即使 token 正确,缺这个参数也会卡在交互式认证环节
最易被忽略的一点:缓存 key 里没包含 PHP 版本或 Composer 版本时,看似命中的缓存,实际可能对应另一个 PHP minor 版本下的产物——vendor 目录能解压成功,但运行时报 Class not found 或 undefined function mb_strlen,这种问题极难复现和定位。











