composer install 默认会安装 require-dev 中的包,但若执行时加了 --no-dev 参数、环境变量 COMPOSER_NO_DEV=1 生效,或 CI/CD 脚本默认启用该选项,则跳过 require-dev 依赖,导致 PHPUnit 等开发工具不被安装。

composer install 为什么没装 require-dev 里的包
默认情况下 composer install 会安装 require 和 require-dev 中的所有依赖,但前提是没加 --no-dev 参数,也没在环境变量里设置 COMPOSER_NO_DEV=1。CI/CD 流水线或某些部署脚本常默认启用 --no-dev,导致 PHPUnit、PHPStan 这类开发工具根本不会出现在 vendor/ 里。
验证方式很简单:
运行 composer install -v(加详细日志),看输出里有没有类似 Loading composer repositories with package information 后跟 Installing dependencies (including require-dev) 的提示;如果没有“including require-dev”,说明 dev 包被跳过了。
- 临时启用 dev 包:加
--dev或去掉--no-dev - 永久生效:检查项目根目录是否有
.env或composer.json里是否配置了"config": {"platform": {"php": "..."}}干扰解析 - 注意:如果已有
composer.lock,它里面已记录是否包含 dev 包 —— 改参数不会自动重写 lock 文件,得先删 lock 再 install(不推荐)或用composer update --lock
require-dev 里装了 phpunit,但 vendor/bin/phpunit 找不到命令
不是所有包都自动注册可执行文件。只有包的 composer.json 明确声明了 "bin" 字段(如 "bin": ["phpunit"]),Composer 才会在 vendor/bin/ 下创建软链接或复制脚本。
常见情况:
– phpunit/phpunit 自 v9.3+ 起已移除 bin 字段,改由 Composer 自动识别 bin/phpunit 入口,但需确保其 composer.json 的 autoload.bin 配置正确;
– 某些镜像源同步滞后,拉下来的包版本旧(比如 v8.x),而旧版可能没配 bin;
– 你用了 composer install --no-scripts,跳过了生成 bin 脚本的 post-install-cmd。
- 手动检查:进
vendor/phpunit/phpunit/目录,看是否存在phpunit或phpunit.phar文件 - 强制重建:删掉
vendor/bin/phpunit,再运行composer dump-autoload --optimize - 安全调用方式:直接用
vendor/bin/phpunit(Linux/macOS)或vendor\bin\phpunit(Windows),别依赖全局 PATH
composer update --dev 和 composer update 有啥区别
composer update 默认更新全部依赖(require + require-dev),而 composer update --dev 是冗余参数——它和不加一样,因为 dev 包本来就是默认目标。真正有用的组合是:
-
composer update --with-dependencies:更新指定包及其传递依赖(比如更新phpstan/phpstan时,顺带更新它依赖的phpstan/phpdoc-parser) -
composer update --no-dev:只更新生产依赖,跳过 dev 包(上线前常用) -
composer update phpunit/phpunit --with-all-dependencies:精准升级一个 dev 工具,并确保它的整个依赖树都兼容
⚠️ 注意:composer update 会重写 composer.lock,且可能升级到不兼容的新主版本(如从 symfony/console:^5.4 升到 ^6.0)。开发环境想保稳定,优先用 composer install;只有明确需要新特性或修复时,才用 update 并立刻提交新的 composer.lock。
离线环境怎么装 require-dev 依赖
离线装 dev 包的关键不是“能不能装”,而是“能不能跑”。很多 dev 工具(如 phpstan/phpstan、laravel/pint)依赖特定 PHP 扩展(ast、tokenizer)或系统命令(git、node),这些在目标机器上必须提前就位。
可靠做法分三步:
1. 在网络通畅的同构环境(相同 PHP 版本、扩展、OS 架构)执行:composer install --no-interaction --no-plugins --no-scripts --optimize-autoloader
2. 打包整个 vendor/ 和 composer.lock(别漏掉 vendor/bin/ 下的可执行文件)
3. 目标机上先验证基础环境:php -m | grep -E 'ast|tokenizer',再运行 php vendor/autoload.php 确认能加载
- 不要用
composer require --dev在离线机上执行 —— 它必然失败 - 如果 dev 包含编译步骤(如
ext-protobuf),离线方案不可行,必须提前编译好扩展.so/.dll - 某些包(如
phpunit/phpunit)的bin/phpunit是纯 PHP 脚本,可直接复制使用,无需 Composer 参与


















