composer analyse —— 静态分析工具 PHPStan 完全指南
一、PHPStan 是什么?
PHPStan 是 PHP 生态中最广泛采用的静态分析工具,它可以在不运行代码的情况下,通过分析代码的语法、类型和调用链,提前发现潜在的逻辑错误和 Bug。是现代 PHP 项目的标配工具之一。
核心价值
PHPStan 的核心价值在于在代码运行前发现问题。与单元测试不同,单元测试需要编写测试用例并实际执行代码,而静态分析则通过扫描源码即可完成检查,成本更低、覆盖更广。
例如,假设有以下代码:
public function getUser(int $id): User
{
return User::find($id);
}
User::find() 在未找到记录时可能返回 null,但方法声明只返回 User 类型。PHPStan 会立即报告:
Method getUser() should return User but returns User|null.
这种类型不匹配问题如果不经静态分析,可能要等到生产环境运行时才会暴露。
PHPStan 的检查级别
PHPStan 采用0–9 共 10 个检查级别,级别越高检查越严格:
| 级别 | 检查内容 |
|---|---|
| 0 | 基础检查:未定义的类、函数、方法调用 |
| 1 | 未定义的变量、未知的魔术方法 |
| 2 | 返回值类型、参数类型(基于 PHPDoc) |
| 3 | 死代码检测、恒真/恒假条件 |
| 4 | 方法调用时的参数类型检查 |
| 5 | 强制类型提示(missing typehints) |
| 6+ | 并集类型严格检查(逐步增加严格度) |
渐进式采用的策略:对于已有项目,建议从 level 0 或 level 1 开始,逐步提升。每次提升级别时,如果错误过多,可先生成基线文件(baseline)将现有问题暂时忽略,之后只关注新增问题。
二、真实场景配置与使用
场景示例:通用 PHP 项目的 PHPStan 配置
对于非 Laravel 的 PHP 项目(如 Hyperf、Symfony、原生 PHP 应用),标准 PHPStan 配置即可满足需求。
步骤一:安装
composer require --dev phpstan/phpstan
步骤二:创建配置文件 phpstan.neon.dist
parameters:
phpVersion: 70400 # 指定项目最低 PHP 版本
level: 7 # 推荐 level 7 作为严格检查起点
paths:
- src
- tests
excludePaths:
- src/legacy
- tests/fixtures
scanDirectories:
- vendor/your-framework/src # 如需要解析框架辅助函数
scanDirectories 的使用场景:如果项目依赖大量全局辅助函数(如 env()、config()、service()),且这些函数定义在框架源码中,PHPStan 需要扫描框架源码才能正确解析这些函数。这时将框架源码目录加入 scanDirectories,PHPStan 就能发现所有框架提供的函数和类定义,而不会将框架本身作为分析目标。
步骤三:在 composer.json 中定义脚本
{
"scripts": {
"analyse": "vendor/bin/phpstan analyse --memory-limit=-1"
}
}
--memory-limit=-1 表示不限制内存,适用于大型项目。
步骤四:运行分析
composer analyse
三、高级配置详解
3.1 并行处理配置
PHPStan 默认启用多线程并行处理,以充分利用多核 CPU:
parameters:
parallel:
jobSize: 20 # 每个作业处理的文件数
maximumNumberOfProcesses: 8 # 最大并行进程数
minimumNumberOfJobsPerProcess: 2
processTimeout: 600.0 # 进程超时时间(秒)
loadLimit: 0.7 # 可用 CPU 使用率上限
- 如果遇到
Child process timed out错误,适当增加processTimeout - 在资源受限环境中,可设置
maximumNumberOfProcesses: 1关闭并行
3.2 生成基线(Baseline)
对于已有项目,一次性修复所有问题不现实。PHPStan 支持生成基线文件:
vendor/bin/phpstan analyse --generate-baseline
执行后会生成 phpstan-baseline.neon 文件,记录当前所有错误。后续运行 PHPStan 时,这些错误会被忽略,只会报告新增错误。在配置文件中引用基线:
includes:
- phpstan-baseline.neon
适用场景:遗留项目升级检查级别时,可以先稳定在低级别,逐步修复基线中的问题。
3.3 编辑器集成(PhpStorm)
PhpStorm 内置了 PHPStan 集成支持,使用 Composer 安装 PHPStan 后,IDE 会自动检测并启用:
- PhpStorm 会自动检测
vendor/bin/phpstan可执行文件 - 在
Settings → PHP → Quality Tools → PHPStan中可配置 PHP 解释器和 PHPStan 路径 - 启用后,PHPStan 的检查结果会实时高亮显示在编辑器中,并与 PhpStorm 原生检查区分(带有
phpstan前缀) - 批量运行时,错误会显示在 Problems 工具窗口中
对于 Docker Compose 环境,需要确保使用 docker-compose exec 模式。
3.4 扩展 PHPStan:数据提取能力
PHPStan 不仅用于错误检查,还可以提取代码库的结构化数据,用于生成文档、调用图等。
核心机制是通过三个扩展点配合工作:
- Collector(收集器):遍历 AST,收集数据
- Rule(规则):处理收集到的数据,包装为带元数据的规则错误
- Error Formatter(错误格式化器):将元数据输出为 JSON 等格式
例如,stella-maris/callmap 扩展利用此机制生成整个项目的方法调用映射,可视化代码依赖关系。
四、IDE 实时检查配置
除了 PhpStorm 的内置集成,VS Code、Vim、Emacs 等编辑器也支持通过 LSP 或插件实现 PHPStan 实时检查。
推荐配置要点:
- 在编辑器中启用 PHPStan 实时检查后,编 辑器界面应分割显示,一边是代码,一边是分析结果
- 实时反馈能大幅提升开发效率,实现「与 PHPStan 结对编程」的体验
五、完整案例:为 Hyperf 项目配置 PHPStan
场景:为 Hyperf 框架项目配置静态分析,从 level 0 起步,逐步提升到 level 7。
步骤一:安装
composer require --dev phpstan/phpstan
步骤二:创建 phpstan.neon.dist
parameters:
phpVersion: 80100 # PHP 8.1
level: 0 # 从最低级别开始
paths:
- app
excludePaths:
- app/config
- app/migrations
scanDirectories:
- vendor/hyperf/framework/src
- vendor/hyperf/utils/src
# 忽略缺失的 PHPDoc 类型
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
步骤三:首次运行并生成基线
vendor/bin/phpstan analyse --generate-baseline
步骤四:在 composer.json 中添加脚本
{
"scripts": {
"analyse": "vendor/bin/phpstan analyse --memory-limit=-1"
}
}
步骤五:逐步提升级别
在 phpstan.neon.dist 中将 level 从 0 改为 1,运行 composer analyse,修复新增错误。重复此过程,直到达到目标级别(建议至少 level 6)。
步骤六:集成到 CI 流程
# .github/workflows/ci.yml
- name: Run PHPStan
run: composer analyse
六、常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
Allowed memory size exhausted | 设置 --memory-limit=2G 或 -1 |
Child process timed out | 增加 parallel.processTimeout 配置 |
| 框架辅助函数无法解析 | 使用 scanDirectories 扫描框架源码 |
| 魔术方法/属性报错(Laravel Eloquent) | 使用 Larastan 替代原生 PHPStan |
| 错误过多无法一次性修复 | 使用 --generate-baseline 生成基线 |
| 检查级别升级困难 | 逐级提升,每级稳定后再升一级 |
七、总结
PHPStan 作为 PHP 静态分析的标准工具,通过可渐进提升的检查级别、基线管理和丰富的扩展生态,能够适配从全新项目到遗留系统的各种场景。配合 IDE 集成和 CI 自动化,它可以成为代码质量保障体系中不可或缺的一环。
最佳实践建议:
- 新项目:直接使用 level 7 或 level 8
- 遗留项目:从 level 0 起步,每稳定一个级别提升一级
- Laravel 项目:使用 Larastan 替代原生配置
- CI 集成:作为 PR 合并的门禁条件,检查不通过则阻止合并
- 编辑器集成:启用 IDE 实时检查,在编码过程中即时获得反馈