PHPStan 必须本地安装、显式加载 autoload 并配置 paths 和 level,否则无法识别类;报 Class not found 通常是 autoloader 未加载,而非代码错误。

PHPStan 不能靠 Composer “配合”就自动检查依赖类型——它必须本地安装、显式加载 autoload、并配置 paths 和 level,否则连你自己的类都找不到,更别说依赖了。
phpstan analyse 报 Class not found 却不是代码问题
这是最典型的假阳性信号:不是类写错了,是 PHPStan 根本没加载你的自动加载器。
- 全局安装
phpstan/phpstan必然失败——它看不到vendor/autoload.php,也读不到composer.json里的autoload映射 - 即使本地安装,若没在
scripts或命令行里显式加--autoload-file=vendor/autoload.php,PHPStan 就不会注册项目类路径 - 用
vendor/bin/phpstan analyse src/但没配paths,它可能只扫src/下有class或namespace声明的文件,纯函数文件(如helpers.php)直接跳过 - 验证是否生效:加
-v参数运行,输出里必须出现Loading autoloader和Loading configuration
composer.json scripts 里 "analyse" 怎么写才真正起作用
写成 "analyse": "phpstan analyse" 是常见陷阱——它依赖 PATH 查找,极大概率调用的是全局二进制或根本不存在的命令。
- 必须用
vendor/bin/phpstan路径,确保调用的是当前项目的版本 - 必须带
--configuration=phpstan.neon,否则 PHPStan 只做 level 0 语法检查,且不读任何自定义规则 - 必须带
--autoload-file=vendor/autoload.php,尤其当项目有自定义autoload.files或测试环境时 - 正确示例:
"analyse": "vendor/bin/phpstan analyse --configuration=phpstan.neon --autoload-file=vendor/autoload.php"
phpstan.neon 配置中 paths 和 autoload_files 容易漏掉的关键项
paths 不是“放得越多越好”,而是“必须覆盖所有实际参与类型推导的代码入口”;autoload_files 则决定了 PHPStan 能“看见”哪些符号。
立即学习“PHP免费学习笔记(深入)”;
-
paths至少包含src/,如果分析测试用例,还得加tests/;Laravel 项目要加app/、database/、routes/ - 若项目用
autoload.files加载全局函数(如"autoload": { "files": ["src/helpers.php"] }),必须在phpstan.neon中重复声明:parameters: { autoload_files: ["src/helpers.php"] } - 第三方扩展(如
phpstan-laravel)需通过includes引入,不能只靠 composer require —— 漏掉vendor/phpstan/phpstan-laravel/extension.neon就会导致 Facade 方法全报错 - 不要把
phpstan.neon放进tools/子目录再用--configuration=tools/phpstan.neon:路径是相对于composer run执行目录,不是composer.json位置
CI 环境下 PHPStan 静默通过但本地报错?先查这三件事
CI 里 [OK] No errors 很可能是 PHPStan 根本没扫描任何文件,而不是代码真的没问题。
- 确认 CI 步骤中执行了
composer install --no-interaction --prefer-dist,且没加--no-dev(否则phpstan/phpstan不会被安装) - 确认
phpstan.neon没被.gitignore忽略,且文件权限允许读取 - 确认 CI 工作目录是项目根目录,不是子模块或缓存路径——否则
--configuration=phpstan.neon会找不到文件 - PHP 版本差异也会导致行为不一致:比如本地 PHP 8.2,CI 用 PHP 8.1,而
phpstan.neon里phpVersion: 80200就会让 CI 环境降级为宽松模式
真正麻烦的从来不是装不上,而是装上了却以为它在检查——结果 paths 漏目录、autoload-file 没指定、phpVersion 没对齐,CI 里一切正常,上线后才发现类型契约早断了。



















