ci 中必须用 composer install 而非 update,因其严格按已提交的 composer.lock 安装,保障版本锁定、顺序一致与结果可重现;update 会重算依赖、生成新 lock,破坏构建确定性,并绕过代码审查。

CI 里为什么必须用 composer install 而不是 composer update
因为 composer update 会重算依赖树、生成新 composer.lock,破坏构建可重现性——CI 不是开发环境,它不负责“决定该装什么”,只负责“按约定装对的东西”。
-
composer install严格按已提交的composer.lock安装,版本锁定、顺序一致、结果可预测 -
composer update在 CI 中运行等于悄悄绕过代码审查:你 merge 的是旧 lock,CI 却装了新版本,可能引入 BC break 或安全漏洞 - GitHub/GitLab 默认拉取的是 clean checkout,没缓存、没 vendor、没临时文件——只有
composer.lock存在,install才能成功;没它,直接报错Composer could not find a composer.json file或更隐蔽的Root package 'xxx' cannot be found
缓存 ~/.composer/cache 比缓存 vendor/ 更重要
缓存 vendor/ 看似快,实则风险高:不同分支、不同 PHP 版本、不同 composer.lock 哈希下复用 vendor 会导致 class not found、autoloader 错乱甚至测试通过但线上炸锅。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 应优先缓存
~/.composer/cache(含 dist zip、git clones、metadata),这是跨项目、跨 job 复用的基础下载产物 - GitHub Actions 示例:
actions/cache@v4缓存路径设为~/.composer/cache,key 用${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} - GitLab CI 可写:
cache: { key: "$CI_COMMIT_REF_SLUG", paths: ["~/.composer/cache"] };别把vendor/写进cache.paths,除非你用 lock 哈希做二级 key 并确保 PHP platform 严格一致
--no-dev --optimize-autoloader --classmap-authoritative 这三个参数缺一不可
生产构建漏掉任一个,轻则 autoload 慢 2–3 倍,重则因 dev 包缺失导致 Fatal error: Class 'PHPUnit\Framework\TestCase' not found 这类运行时崩溃(尤其当你用了 class_exists() 做特性探测时)。
-
--no-dev:跳过require-dev里的包,避免把phpunit、symfony/debug-bundle打进线上镜像 -
--optimize-autoloader:生成vendor/composer/autoload_classmap.php,绕过 PSR-4 动态查找,提速明显 -
--classmap-authoritative:告诉 autoloader “classmap 里没有的类,就真的不存在”,彻底禁用文件系统扫描,既提速又防误加载 - 注意:这三个参数只应在 CI 的「构建」或「部署」阶段加,测试阶段仍需保留
require-dev和完整 autoload
PHP 版本与扩展不匹配,是 composer install 静默失败最常见原因
不是报错退出,而是跳过某些包、生成异常 classmap、甚至让 composer validate 通过但运行时报 undefined function mb_strlen()——这类问题最难 debug,因为日志里没 warning。
- 检查
composer.json里的"config": { "platform": { "php": "8.1.10" } }是否与 CI 实际 PHP 版本一致;否则 Composer 会按本地版本解析依赖,而 CI 运行时却用低版本 PHP - Alpine 镜像默认不带
ext-zip、ext-pdo、ext-mbstring,得显式安装,例如:apk add php81-zip php81-pdo php81-mbstring - 私有包认证失败常表现为卡在某个包不动,或报
Could not fetch https://repo.example.com/packages.json;正确做法是 CI 脚本中动态注入:composer config http-basic.repo.example.com $USERNAME $TOKEN,而非提交auth.json










