Composer install 默认只安装 production 依赖,即仅按 composer.lock 中记录的 require 包安装,忽略 require-dev;若需安装开发依赖,须显式加 --dev 参数,而生产部署必须用 --no-dev 确保跳过 dev 包。

composer install 默认只装 production 依赖
运行 composer install 时,它不会无差别安装 require-dev 里的包,除非你显式告诉它要装。这是 Composer 的默认行为——只根据 composer.lock 中记录的 production 依赖来安装,忽略 require-dev。如果你本地开发需要 phpunit 或 larastan 这类工具,直接跑 composer install 后它们根本不会出现在 vendor/ 里。
常见错误现象:vendor/bin/phpunit 找不到、IDE 提示 Class 'Tests\TestCase' not found、CI 流水线本地复现失败。
- 加
--dev参数:composer install --dev(等价于--with-all-dependencies,会装require+require-dev) - 加
--no-dev参数:强制跳过require-dev,适合部署到生产环境 - 不加任何参数:行为取决于
COMPOSER_NO_DEV环境变量是否为 true;若未设置,则按composer.lock记录安装(通常不含 dev 包)
用 COMPOSER_ENV 或平台配置区分环境逻辑
Composer 本身没有 environment=staging 这种原生概念,但你可以通过组合 config.platform 和条件性 require-dev 实现近似效果。比如在 composer.json 中写:
"config": {
"platform": {
"php": "8.1.0"
}
},
"require-dev": {
"symfony/var-dumper": "^6.2",
"pestphp/pest": "^2.0"
}
这样做的本质是「锁定 PHP 版本」或「模拟目标环境能力」,避免本地高版本 PHP 装了不兼容的扩展,导致上线后报错。但注意:platform 不影响包是否被安装,只影响依赖解析时的版本选择逻辑。
- 想让某些 dev 包只在 CI 中启用?用
scripts+ 环境变量判断,例如在composer.json中定义:"scripts": {"ci-install": "COMPOSER_NO_DEV=0 composer install"} -
require-dev中的包如果带autoload-dev,其自动加载规则默认不生效,除非你手动 require 或运行composer dump-autoload --dev - CI 环境中建议始终显式使用
--no-dev或--dev,避免因环境变量差异导致行为不一致
composer.lock 文件决定了 install 的确定性
composer install 的核心意义就是「按 lock 文件精确还原」。它不读 composer.json 的最新版本约束,而是照着 composer.lock 里每个包的 exact commit hash / version / source URL 去拉取。所以哪怕你本地 composer.json 里写的是 "monolog/monolog": "^3.0",只要 lock 文件锁的是 3.4.0,install 就只会装 3.4.0。
- 团队协作中,必须提交
composer.lock;否则每人composer install可能装出不同版本 - 想升级某个 dev 包?别直接改 lock 文件,用
composer update --dev monolog/monolog,再提交更新后的 lock - 误删了
vendor/和composer.lock?composer install会失败,此时必须先composer update生成新 lock,再 install —— 但这已不是“确定性还原”了
CI/CD 中 install 命令的典型写法
多数 CI 平台(GitHub Actions、GitLab CI)默认不设 COMPOSER_NO_DEV,所以 composer install 行为可能和你本地不一致。最稳妥的做法是显式声明意图。
- 测试环境(含 PHPUnit、PHPStan):
composer install --no-interaction --prefer-dist --dev - 生产构建(Docker 镜像):
composer install --no-interaction --no-dev --optimize-autoloader --classmap-authoritative -
--no-interaction是必须的,避免 CI 卡在交互式提示上;--prefer-dist加速下载,--optimize-autoloader减少运行时开销 - 如果项目用了
composer-plugin-api类插件(如hirak/prestissimo),注意某些旧版插件在--no-dev下可能异常退出,建议升级或移除
真正容易被忽略的点是:lock 文件的生成环境和 install 环境的 PHP 版本要尽量一致。PHP 8.2 下生成的 lock,拿到 PHP 8.0 环境里 install 可能因 platform 配置触发降级或报错,而不是安静地装完。


















