require-dev不是环境开关而是安装标记,是否进入生产环境取决于部署时是否执行composer install --no-dev;漏掉该参数或lock文件含dev记录,将导致phpunit等包被误装入生产环境。

require-dev 不是环境开关,是安装标记
很多人以为把包放进 require-dev 就等于“只在开发环境生效”,其实它只是告诉 Composer:“这个包,我只在本地跑命令时需要”。真正决定它会不会进生产环境的,是部署时有没有加 --no-dev。不加,哪怕你写一百遍 composer require --dev phpunit/phpunit,线上照样会装上 PHPUnit——不是“可能”,是必然。
线上报 Class not found?先查代码越界调用
典型现象:本地测试全绿,CI 或线上直接 Class 'PHPUnitFrameworkTestCase' not found。这不是 Composer 没装对,而是你的业务代码越界引用了 dev 包里的类。常见位置包括:
-
app/Providers/AppServiceProvider.php里无条件调用了dump()(来自symfony/var-dumper) -
config/app.php的'providers'数组里写了BarryvdhDebugbarServiceProvider::class,没套环境判断 -
database/migrations/的up()方法里用了DoctrineDBALTypesTypes,而该包只在require-dev
验证方式:在生产环境执行 php -r "var_dump(class_exists('PHPUnitFrameworkTestCase'));",返回 bool(false) 才算干净。
composer install --no-dev 为什么有时没用?锁文件说了算
--no-dev 只过滤安装行为,但前提是 composer.lock 里没存 dev 包记录。如果上次是 composer update(没加 --no-dev)生成的 lock 文件,那里面就含 "name": "phpunit/phpunit" 在 packages 数组里——此时 composer install --no-dev 也救不了你。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
正确流程必须是:
- CI 构建前先跑:
composer update --no-dev --lock,确保 lock 文件只记录 runtime 依赖 - 部署阶段只用:
composer install --no-dev --optimize-autoloader - 补一步清理:
composer dump-autoload --no-dev,否则vendor/composer/autoload_dev.php可能残留,被某些框架误加载
autoload-dev 路径不会自动消失,得手动防污染
autoload-dev 是给测试类、fixture、CLI 工具用的 PSR-4 映射,比如 "Tests\": "tests/"。但它和 require-dev 是两件事:即使你没装 PHPUnit,只要 composer.json 里配了 autoload-dev,composer dump-autoload 默认就会把它写进 autoloader——导致线上 autoloader 多加载一堆无用路径,甚至引发命名冲突。
生产镜像构建后务必检查:
-
ls vendor/composer/autoload_dev.php—— 存在即违规 -
grep -n "Tests\" vendor/composer/autoload_classmap.php—— 若有输出,说明测试类路径进了 classmap -
ls vendor/ | grep -E 'phpunit|phpstan|mockery'—— 有结果就是隔离失败
真正的隔离不是靠“加了 --dev”就完事,而是从 lock 文件、autoloader、vendor 目录三个层面同时卡死。漏掉任何一环,dev 包就可能悄悄混进生产环境,体积涨、启动慢、调试入口暴露——这些都不是警告,是已发生的事实。










