require-dev只放开发时必需、运行时完全不需要的工具类包,如phpunit/phpunit、phpstan/phpstan、php-cs-fixer等;误放运行时依赖会导致线上报错,误入require则浪费资源并引入风险。

require-dev 只放开发时需要、运行时完全不需要的工具类包,不是“测试用的业务代码依赖”
require-dev 该放哪些包?
它只控制「哪些第三方工具包在开发阶段被安装」,和你的测试类能否自动加载无关。常见内容包括:
-
phpunit/phpunit:执行测试用,生产环境绝不能装 -
phpstan/phpstan、psalm/phar:静态分析工具,CI 流水线里跑,线上无用 -
symfony/debug-bundle:本地调试用,暴露/_profiler接口,线上等于开后门 -
infection/infection:变异测试工具,体积大、启动慢,纯开发阶段使用 -
laravel/pint或friendsofphp/php-cs-fixer:代码风格检查/修复,CI 中可选启用,但不应进生产镜像
错误示例:"require-dev": { "guzzlehttp/guzzle": "^7.0" } —— 这会导致线上发 HTTP 请求失败,因为 Guzzle 没进 require,生产环境根本没装。
为什么 require-dev 里的包线上不能少也不能多?
少:测试或 CI 阶段直接报错,比如 vendor/bin/phpunit 找不到命令;多:增大镜像体积、引入攻击面、甚至触发安全扫描告警。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 上线前用
composer show --dev快速核对,确认没有漏掉必需工具,也没有混入业务依赖 - CI 构建测试阶段必须用
composer install(不加--no-dev),否则 PHPUnit 根本起不来 - 部署到生产环境时,必须加
--no-dev参数:composer install --no-dev --prefer-dist - 某些框架(如 Laravel)的
APP_DEBUG=true会悄悄拉起debug-bundle,若它在require-dev里却没加--no-dev,就等于把调试接口公开到公网
require-dev 和 autoload-dev 完全不是一回事
很多人以为往 require-dev 里加了 phpunit/phpunit,测试类就能自动加载——这是错的。autoload-dev 是另一套配置,专管「你的 tests/ 目录下类文件怎么被 PHP 找到」。
-
require-dev决定「装不装 PHPUnit」 -
autoload-dev决定「new TestsUnitExampleTest()找不找得到这个类」 - 已装 PHPUnit 却报
Class 'TestsUnitExampleTest' not found?大概率是漏了composer dump-autoload --dev,或者autoload-dev的 PSR-4 命名空间没对上路径 - 正确写法示例:
"autoload-dev": { "psr-4": { "Tests\": "tests/" } },对应tests/Unit/ExampleTest.php里必须有namespace TestsUnit;
CI 脚本里最容易踩的 require-dev 坑
不是所有环境都该装 dev 包,但顺序和参数稍错就会连锁失败。
- 测试阶段执行
composer install但没清缓存,可能复用旧 vendor,导致新写的测试类不生效 → 加--no-cache - 误用
composer update --no-dev在测试环境 → 它会忽略composer.lock,重新解析依赖图,引入未验证版本 → 应该用composer install --no-dev - CI 镜像构建分层时,如果先
composer install(含 dev),再删掉vendor/bin/下的 PHPUnit,不如一开始就--no-dev干净 - Git 钩子或 CI 脚本里加校验:
composer validate --strict会揪出require-dev里混入@dev标签的不稳定包
最常被忽略的是:autoload-dev 的变更不会自动生效,哪怕你改了 composer.json,也得手动跑一次 composer dump-autoload --dev,否则新增的测试类永远找不到。










