--no-dev 是生产环境排除调试工具的唯一生效方式,必须显式添加且需配合 clean lock 文件、清理 autoload-dev 及 --optimize-autoloader 和 --classmap-authoritative 参数。

composer install --no-dev 是唯一生效方式
生产环境排除调试工具(如 phpunit、xdebug、laravel-debugbar、phpstan)不是靠配置或环境变量,而是必须在 composer install 命令里显式加 --no-dev。这个参数是硬开关:它跳过 require-dev 字段里所有包的解析、下载、安装和 autoload 注册——连带它们的传递依赖(比如 phpunit 带的 sebastian/exporter)也一并过滤。
常见误操作包括:
- 只删掉
composer.json里的require-dev块——composer.lock仍含旧记录,install会照装 - 设
COMPOSER_NO_DEV=1环境变量——Composer 2.2+ 已弃用,CI 中极易被覆盖,行为不可靠 - 先跑一次没带
--no-dev的install,再补加参数——已装的包不会自动卸载
为什么加了 --no-dev 还有调试工具残留?
根本原因不是参数失效,而是 composer.lock 文件本身“记错了”。只要 lock 文件里有 "packages-dev" 区块,或 "packages" 数组中存在 "phpunit/phpunit" 这类条目,composer install --no-dev 就会照单全收。
验证方法:
- 运行
grep -A5 '"packages-dev"' composer.lock | head -20,输出非空说明 lock 已污染 - 打开
composer.lock搜索"phpunit"、"mockery"、"symfony/debug-bundle",应完全不出现 - 不要复用本地开发生成的 lock 文件,尤其当本地执行过未加
--no-dev的composer update
autoload-dev 映射残留导致 Class not found 假阳性
--no-dev 只控制包是否安装,不清理 autoload-dev 路径映射。只要 composer.json 里还定义了 "autoload-dev": {"psr-4": {"Tests\": "tests/"}},且没执行 composer dump-autoload --no-dev,生成的 vendor/autoload.php 就仍会注册测试路径。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
后果是:class_exists('TestsFooTest') 返回 true,但实际 vendor/phpunit/phpunit 不存在,运行时 new TestsFooTest() 直接报错。
解决办法只有两个:
- 删掉
composer.json中的autoload-dev块,再跑composer dump-autoload - 保留
autoload-dev,但每次部署后补一句composer dump-autoload --no-dev
生产部署命令必须带三参数
光 --no-dev 不够,调试工具可能没装,但加载性能和安全风险仍在。推荐组合:
-
composer install --no-dev:过滤 dev 包 -
--optimize-autoloader:把 PSR-4 映射转为 classmap 条目,减少运行时文件扫描 -
--classmap-authoritative:强制 autoloader 只查 classmap,禁用file_exists()和opendir()
注意:composer dump-autoload -o 在 Composer 2.0+ 中只是 --classmap-authoritative 的别名,不再重建 classmap,容易漏项导致 Class not found;必须用 install 阶段触发完整扫描。
上线前务必检查 vendor/composer/autoload_real.php 的 findFile() 方法——只保留 if ($classMap = $this->classMap) 分支,且彻底删除 PSR-4 循环。










