本地开发时 composer install 默认安装 require-dev 包并加载 autoload-dev;模拟生产环境需执行 composer update --no-dev --lock 生成合规 lock 文件,再运行 composer install --no-dev --optimize-autoloader --classmap-authoritative。

本地开发时,composer install 默认不是生产环境
它会照单全收 require-dev 里的包(比如 phpunit/phpunit、phpstan/phpstan),还会加载 autoload-dev 配置的命名空间。这不是 bug,是 Composer 的默认行为——它不猜你当前在哪儿,只认配置文件里写了啥。
想模拟生产环境,核心是两件事:跳过 dev 包安装 + 禁用 dev 自动加载路径。光靠 composer install --no-dev 不够,因为如果 composer.lock 是之前用 composer update(没加 --no-dev)生成的,那 lock 文件里已经存了 dev 包的记录,--no-dev 就会被忽略。
- 先确保
composer.lock是按生产规则生成的:在干净环境运行composer update --no-dev --lock,再提交 - 接着执行
composer install --no-dev --optimize-autoloader --classmap-authoritative --no-scripts -
--optimize-autoloader重建类映射表,避免运行时反复扫描文件系统 -
--classmap-authoritative强制 autoloader 只查 classmap,不 fallback 到 PSR-4 扫描——这能暴露因命名空间错位或路径未注册导致的“类找不到”问题,反而利于调试
本地包在模拟生产环境时突然报错:Class not found
常见于用 "type": "path" 引入本地包后,composer install --no-dev 成功但运行时报错。根本原因不是包没装上,而是 autoload 规则没生效或被覆盖。
检查三处:
- 主项目
composer.json的repositories是否含"type": "path",且url路径在生产构建机上根本不存在(比如"../my-local-package")→ Composer 直接报错退出,不会 fallback 到 Packagist - 本地包自身的
composer.json中autoload和autoload-dev是否混用:比如把测试工具类写进autoload-dev,又在代码里直接 new 它 →--no-dev后这些路径没注册,必然报错 - 主项目执行
composer dump-autoload不解决路径仓库缺失问题;必须删掉vendor/重装,且确保composer.lock里记录的是符号链接(symlink)而非 zip 包
如何让本地包既可调试,又不污染生产部署
别把 "repositories" 写死在 composer.json 里提交到 Git。这是最常踩的坑——CI 构建或线上部署时,路径不存在就中断,没人能帮你手动改 JSON。
推荐两个轻量方案:
- 用
COMPOSER_REPOSITORIES环境变量临时注入:部署脚本里加COMPOSER_REPOSITORIES='[{"type":"path","url":"../my-local-package"}]' composer require vendor/my-local-package:dev-main,本地开发时设,CI/生产时 unset - 用
studio工具管理:全局安装composer global require franzl/studio,然后在主项目根目录运行studio add ../my-local-package。它会自动在内存中注入路径仓库,不修改composer.json,也不提交任何配置
无论哪种,都要确保本地包有真实远程源(如 GitHub + Packagist),否则生产构建失败时无法降级。
composer show --dev 显示空,但 vendor/ 里仍有 tests 目录
这说明 --no-dev 生效了(dev 包没装),但 autoload-dev 的路径仍留在 autoloader 配置里,或某些包把 tests/ 打进了 dist zip 包里。
这不是 Composer 的错,是包作者打包不规范。生产部署后必须手动清理:
- 删掉所有测试相关路径:
find vendor/ -name 'tests' -o -name 'Tests' -o -name 'test' -o -name 'Test' | xargs rm -rf - 删掉
vendor/bin/下的 dev 工具二进制(如phpunit、php-cs-fixer) - 确认
vendor/composer/autoload_psr4.php里没有"Tests\"或"test\"这类键名;若有,说明某个包的autoload-dev被错误地合并进来了——得去那个包的composer.json提 PR 修复
真正麻烦的不是装多了,而是 autoload 规则残留导致类加载器默默 fallback 到不存在的目录,最后报错位置和实际问题隔了三层。这点很容易被忽略。











