CI必须用composer install而非update,以确保依赖树一致;需校验composer.lock、缓存~/.composer/cache、部署加--no-dev --optimize-autoloader --classmap-authoritative参数,并透传scripts参数。

CI里必须用composer install,禁用composer update
CI流水线不是做依赖决策的地方,它只负责“还原”——还原出和本地、生产完全一致的依赖树。一旦在CI脚本里出现composer update,就会重写composer.lock,哪怕只是monolog/monolog:2.10.0 → 2.10.1这种patch升级,也可能触发未覆盖的边界逻辑,导致测试通过但线上报Class not found或Method not found。
正确做法是:
-
composer install必须有composer.lock文件才能运行;没提交它,CI直接失败 - CI脚本开头加
composer validate --strict,校验composer.json和lock是否匹配 - 本地开发可配
pre-commit钩子:composer install --dry-run,提前发现lock过期
缓存目标只能是~/.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/ - 缓存失效最常见原因:本地手动生成了新
lock但没提交,导致key不匹配,CI每次走冷安装
生产部署必须加--no-dev --optimize-autoloader --classmap-authoritative
这三个参数不是可选项,是autoload性能的底线。不加的话,PHP每次自动加载都要遍历PSR-4映射、执行file_exists()试探,IO开销大,还容易因符号链接、大小写或opcache失效漏类。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
--optimize-autoloader把命名空间映射编译成静态数组;--classmap-authoritative告诉Autoloader:“不在classmap里的类,一律不存在”,跳过所有文件系统探测。
注意:
- 必须配合
--no-dev使用,否则class_exists('PHPUnit\Framework\TestCase')这类运行时判断会直接fatal - 若代码里真有这种判断,得改成
class_exists('PHPUnit\Framework\TestCase', false)或先function_exists()兜底 - Docker构建时,应在
COPY composer.json composer.lock ./后立即RUN composer install --no-dev --optimize-autoloader --classmap-authoritative,利用层缓存
CI中调用自定义scripts要透传参数,别硬编码命令路径
composer.json里的"scripts"是CI标准化执行逻辑的核心。比如写了"test": "phpunit --configuration phpunit.xml",CI就该统一跑composer test,而不是直接调./vendor/bin/phpunit——这样既解耦工具路径,又让本地、CI、生产共用同一套行为。
实操要点:
- 支持参数透传:
composer test -- --filter=TestLogin会原样传给PHPUnit - 别在script里写
./vendor/bin/phpunit,依赖Composer的bin自动发现机制更健壮 - 如需区分环境,可用
COMPOSER_DEV_MODE=0控制是否加载require-dev,但CI通常应保持dev依赖启用(尤其测试阶段)
最容易被忽略的是:缓存key是否真的绑定到composer.lock内容,以及--classmap-authoritative启用后对运行时class_exists()调用的破坏性。这两点不验证,上线后问题往往延迟暴露,排查成本极高。

















