必须同时使用--no-dev、--optimize-autoloader、--classmap-authoritative三个参数:--no-dev跳过dev依赖防止安全风险;--optimize-autoloader生成静态类映射提升加载性能;--classmap-authoritative强制信任映射表,禁用文件系统探测以防Class not found。

CI/CD里直接写composer install就跑,大概率线上出Class not found或响应慢到超时——不是代码问题,是命令漏参数、缓存用错位置、脚本没显式触发。
composer install 必须带哪三个参数?
生产构建不加这仨,autoload 就是半残:PHP每次加载类都得扫目录、试探文件存在性,IO压垮小服务器很常见。
-
--no-dev:跳过require-dev里的包(比如phpunit、phpstan),否则可能把调试后门或未审计的远程调用打进线上环境 -
--optimize-autoloader:生成vendor/composer/autoload_classmap.php,把PSR-4映射编译成静态数组,类加载提速50%以上 -
--classmap-authoritative:配合上一个参数,强制 autoloader 相信 classmap,不再 fallback 到文件系统探测——这是防Class not found的最后一道防线
三者必须同时出现。只加前两个,autoloader 仍会悄悄做file_exists();只加--no-dev,autoload 性能原地踏步。
为什么不能在CI里跑 composer update?
composer update会重写composer.lock,导致构建不可重现——今天通过的流水线,明天可能因monolog/monolog从2.10.0升到2.10.1而失败。
-
composer install读composer.lock,装完全一致的版本、顺序、嵌套关系 -
composer update重新解析composer.json,触发依赖图重建、版本重选、lock覆盖 - CI开头应加
composer validate --strict,确保composer.json和composer.lock内容匹配
除非你专门建一条“更新依赖”流水线,否则CI脚本里出现composer update就是事故前兆。
使用 `gh` CLI 与 GitHub 交互。通过`gh issue`、`gh pr`、`gh run` 和 `gh api` 管理 issue、PR、CI 运行以及高级查询。
缓存该缓什么、怎么缓才安全?
缓vendor/是最常见也最危险的直觉错误:vendor/跟PHP版本、OPcache开关、文件系统大小写敏感度强耦合,缓错一次就Cannot declare class。
- 只缓
~/.composer/cache:它只存zip/dist包,跟环境无关,只绑定composer.lock哈希 - GitHub Actions中
key必须含${{ hashFiles('**/composer.lock') }},否则lock一变缓存就失效 - GitLab CI别写
paths: [vendor/],那是自埋雷;正确写法是paths: [~/.composer/cache]
缓存失效最常因为:本地手动生成新composer.lock但没提交,导致CI key不匹配,每次都是冷启动。
post-install-cmd 在CI里默认不执行?
CI环境(如GitHub Actions)默认以COMPOSER_DEV_MODE=0运行,此时post-install-cmd和post-update-cmd被禁用——不是bug,是Composer v2+的安全策略。
- 别指望它自动触发,它在CI里基本等于“不可靠”
- 解法一:
composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction之后,补一句composer run-script post-install-cmd --no-dev - 解法二:改用自定义脚本名(如
deploy:post-install),并在CI步骤中明确调用composer run deploy:post-install,逻辑更可控
真正容易被忽略的是:即使所有参数都对、缓存也生效,如果post-install-cmd没显式调用,像生成配置、清理runtime、设置权限这类动作就根本不会发生——线上跑起来才发现runtime/cache没写权限,或者.env没复制。

















