线上报class not found的根本原因是代码越界调用了require-dev包中的类,而--no-dev仅跳过安装但未阻止autoload-dev映射残留,导致生产环境autoloader无法找到该类。

require-dev 本身不隔离环境,它只声明“这不是生产必需的依赖”;真正起隔离作用的是部署时是否加 --no-dev。
为什么线上还报 Class not found?
常见现象:本地用 composer require --dev phpunit/phpunit,生产跑 composer install --no-dev,但启动时仍报 PHPUnitFrameworkTestCase 找不到。
- 根本原因不是 Composer 没跳过安装,而是代码里写了
class_exists('PHPUnitFrameworkTestCase')或use PHPUnitFrameworkTestCase—— 这类调用在生产 autoloader 中根本不存在该类,PHP 直接 fatal -
autoload-dev路径不会因--no-dev自动从主 autoloader 中剔除;如果某个包在require-dev里定义了"autoload-dev": {"psr-4": {"Tests\": "tests/"}},composer dump-autoload默认仍会把它写进vendor/autoload.php,导致命名冲突或 autoload 失败 - 验证方式:上线后进容器执行
ls vendor/phpunit,输出为空才说明没装;再查grep -r "PHPUnit" vendor/composer/autoload_classmap.php,应无结果
composer install --no-dev 有时没用?
不是命令失效,是 composer.lock 文件本身记录了 dev 包。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer install只照lock文件装,不看composer.json里的require-dev字段。如果你上次运行的是composer update(没加--no-dev),lock文件就已固化所有 dev 包的版本和哈希 - CI 构建前必须先跑:
composer update --no-dev --lock,再提交更新后的composer.lock - Dockerfile 中推荐写死:
RUN COMPOSER_DEV_MODE=0 composer install --no-dev --optimize-autoloader,双重保险
哪些包看似是 dev,实为运行时依赖?
不能只看用途,要看它是否被 src/ 或配置文件直接引用。
- 该放
require-dev:phpunit/phpunit、phpstan/phpstan、larastan/larastan—— 它们只在 CLI 下执行,不参与 HTTP 生命周期 - 不该放
require-dev:symfony/var-dumper(若dump()出现在AppServiceProvider)、barryvdh/laravel-debugbar(若providers数组里没套if (app()->environment('local')))、doctrine/doctrine-bundle(Bundle 启动即注册) - 检查方法:
grep -r "use.*PHPUnit|dump(|class_exists.*Test" src/ config/,任何命中都说明它越界了
最易忽略的一点:autoload-dev 规则不会自动消失,即使包没装,它的 PSR-4 映射仍可能留在 autoloader classmap 里——这会导致生产环境加载路径变长、性能下降,甚至触发错误的类查找逻辑。










