require-dev 与 require 的区别在于:前者仅用于开发环境,不参与生产依赖树,执行 composer install --no-dev 时不会安装其中的包(如 phpstan、psalm),避免线上误加载或冲突;工具是否可用取决于是否存在于 vendor/bin/,而非 autoload-dev 配置。

require-dev 装静态分析工具,和 require 有啥区别?
require-dev 里的包只在开发环境生效,不会打进生产依赖树,也不会被 composer install --no-dev 加载。静态分析工具(比如 phpstan、psalm、phpcs)本就不该出现在线上,装错位置会导致部署时意外拉取大量 dev-only 依赖,甚至因自动加载冲突引发报错。
- 生产部署执行
composer install --no-dev后,require-dev下的工具完全不可用,这是预期行为 -
autoload-dev配置仅影响类自动加载,不影响工具本身是否可用;工具能否运行,只看它是否在vendor/bin/下存在可执行文件 - 如果误塞进
require,CI 流水线可能正常,但上线时--no-dev会让phpstan命令突然“消失”,排查起来容易绕弯
怎么加 phpstan / psalm 到 require-dev?
直接改 composer.json 的 require-dev 段,然后 composer update。别用 composer require xxx --dev 自动写入——它默认不加版本约束,容易锁死不兼容大版本。
- 推荐显式指定稳定小版本范围,比如:
"phpstan/phpstan": "^1.10",避免^1在未来拉到 v2 导致配置格式不兼容 -
psalm要注意:v5 开始强制要求 PHP 8.1+,如果项目还跑在 7.4,得锁"vimeo/psalm": "^4.30" - 安装后检查
vendor/bin/phpstan是否存在,不存在可能是 composer 缓存没刷新,试下composer clear-cache && composer install --dev
为什么 vendor/bin/ 下的命令有时找不到?
不是所有工具都自动注册二进制入口。有些包(比如旧版 squizlabs/php_codesniffer)需要额外配置 bin 字段或手动 symlink,而新版大多已内置。
-
phpstan和psalm默认就写进composer.json的bin,安装完就能直接vendor/bin/phpstan -
php-cs-fixer是例外:它用friendsofphp/php-cs-fixer包,但二进制名是php-cs-fixer,不是包名,别按包名猜命令 - Windows 下若提示“不是内部或外部命令”,大概率是没开
vendor/bin的路径,或者用了 Git Bash 但没启用msys2兼容模式;优先用php vendor/bin/phpstan绕过 shell 解析问题
本地跑得通,CI 却报 command not found?
CI 环境常省略 --dev 或默认走 --no-dev,尤其用 composer install 不带参数时,行为取决于 COMPOSER_DEV_MODE 环境变量或 composer.json 的 config.platform 设置。
- GitHub Actions / GitLab CI 中,确保步骤明确写
composer install --no-interaction --prefer-dist—— 这个组合默认包含 dev 依赖;如果加了--no-dev,就得删掉 - Docker 构建时,
composer install若在多阶段中发生在 builder 阶段,要确认该阶段没设--no-dev - 最稳妥的是在 CI 脚本里加一句
ls -la vendor/bin/ | grep -E "(phpstan|psalm|php-cs-fixer)",快速验证工具是否真被装进去了
静态分析工具装在哪,表面是配置问题,实质是环境边界意识。很多人调通本地就以为万事大吉,结果上线前一测,发现 phpstan 根本不在 vendor/bin 里——因为构建镜像时用了 --no-dev,而自己从没在本地模拟过这个场景。










