PHPStan 或 Psalm 扫描 vendor/ 是因配置中 paths 过宽(如 ["."])、scanFiles 包含 vendor 文件,或自动发现机制触发全盘扫描;应显式限定 paths 为 src/ 和 tests/ 并检查外部配置。

为什么 phpstan 或 psalm 会扫描 vendor/ 目录?
默认情况下,这些工具不会主动扫描 vendor/,但一旦你在配置中写了宽松的 paths(比如 ["."]),或启用了 scanFiles 并意外包含 vendor/ 下的文件,它们就会尝试解析——而这时往往报错:Permission denied、Cannot open file vendor/xxx/autoload.php,甚至直接 crash。
根本原因不是“权限不足”,而是工具在解析时试图读取或加载 vendor/ 中的 PHP 文件(尤其是带语法错误、PHP 版本不兼容、或含动态代码的第三方包),而这些文件本就不该被静态分析。
如何快速确认是否误扫 vendor/?
运行时加 --debug 或 -v 参数,观察输出中最早出现的报错路径是否落在 vendor/ 内:
vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php: Permission denied
如果看到这类路径,基本可以断定配置越界。此时别急着改 chmod,先检查工具自身的路径配置逻辑:
-
phpstan.neon中的parameters.paths是否包含.或src/外的目录 -
psalm.xml中的<projectfiles></projectfiles>下有没有<directory name="."></directory>这类宽泛声明 - 是否通过
--autoload-file指向了vendor/autoload.php—— 这本身合法,但若同时又让工具去“解析”这个文件,就容易触发对vendor/的递归遍历
composer install 后的 vendor/ 权限问题怎么处理?
Composer 默认不修改 vendor/ 下文件的可读性,但某些系统(如 WSL、Docker 容器、CI 环境)可能因 umask 或挂载方式导致文件不可读。这不是 Composer 的 bug,而是环境行为:
- Linux/macOS 下,用
find vendor -type f -not -readable -ls快速定位不可读文件 - 临时修复可用
chmod -R a+r vendor/,但仅用于调试——生产 CI 中应避免,改用更精确的路径排除 - 更稳妥的做法是:在 CI 脚本里加一步
composer install --no-dev(减少无关包),再确保静态分析只作用于src/和tests/
真正要堵住的入口:配置里的路径泄漏
最常被忽略的是工具自动发现机制。例如 Psalm 在找不到 psalm.xml 时会 fallback 到扫描当前目录;PHPStan 在无配置时默认分析 src/,但如果你手动指定了 --configuration=phpstan.neon,而该文件内容为空或只写了 includes: 却没设 paths,它就可能退化为全盘扫描。
务必显式声明分析范围:
parameters:
paths:
- src/
- tests/不要依赖“默认值”——尤其在 monorepo 或含 legacy 代码的项目里,vendor/ 上层目录结构稍有变化,就可能让相对路径意外覆盖到它。
复杂点在于:有些工具(如 PHPStan)的扩展或插件会悄悄往 paths 里追加目录,得查 includes 引入的外部配置是否藏了隐患。


















