PHPStan 错误标识符 div.rightNonNumeric 详解:除法运算符右操作数不是数值类型
【免费下载链接】phpstanPHP Static Analysis Tool - discover bugs in your code without running it!项目地址: https://gitcode.com/gh_mirrors/ph/phpstan
导读
div.rightNonNumeric是 PHPStan 在启用 phpstan-strict-rules 为骨架,结合 errorsIdentifiers.json 中的规则映射与同族文档,完整讲解该错误的触发条件、PHP 语言语义依据、两种修复思路,以及与之配套的同类算术运算检查(+、-、*、%、**)。读完你将对 strict-rules 的"运算数必须是数值"系列规则形成系统认识,并能直接在自己的项目里复现、修复并配置该检查。
错误标识符是什么:一条错误的前缀编号
在 PHPStan 2.x 中,每条错误都可以携带一个机器可读的错误标识符,格式类似div.rightNonNumeric。其中:
div表示该错误与除法(division)运算相关;rightNonNumeric表示问题是"右侧操作数不是数值类型";- 与之对应,div.leftNonNumeric.md 负责描述"左侧操作数不是数值类型"的情形。
该文档文件的 frontmatter 记录了它的元信息:
title: "div.rightNonNumeric" shortDescription: "Right side of the division operator is not a numeric type." ignorable: trueignorable: true表示该错误可以在配置中通过ignoreErrors或基线(baseline)机制显式忽略,与那些->nonIgnorable()的强制错误不同。
触发示例:一段会被报告的代码
文档给出了一个最小化的、必然触发该错误标识符的 PHP 示例:
<?php declare(strict_types = 1); function doFoo(int $numerator, bool $flag): void { $result = $numerator / $flag; }注意示例开头固定使用declare(strict_types = 1);——这是 strict-rules 类检查的典型测试环境,因为非严格模式下 PHP 的弱类型转换会掩盖部分问题。这里$numerator是int,而除号右侧的$flag是bool,bool不属于数值类型,因此 PHPStan 会报告div.rightNonNumeric。
为什么会报告这个错误:规则来源与 PHP 语义
规则来源:phpstan-strict-rules
该错误并非 PHPStan 核心自带,而是由phpstan/phpstan-strict-rules包提供。从本仓库的 errorsIdentifiers.json 可以看到明确的标识符到规则的映射:
"div.leftNonNumeric": → PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule (line 51) "div.rightNonNumeric": → PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule (line 59)也就是说,div.leftNonNumeric与div.rightNonNumeric都由同一个规则类OperandsInArithmeticDivisionRule报告,只是分别覆盖操作符的左侧(源码第 51 行附近)与右侧(源码第 59 行附近)的检查逻辑。该规则类位于 phpstan-strict-rules 包的src/Rules/Operators/目录下。
要在项目中使用这条规则,需要安装并启用 strict-rules,典型的做法是:
composer require --dev phpstan/phpstan-strict-rules然后在phpstan.neon中包含其规则文件:
includes: - vendor/phpstan/phpstan-strict-rules/rules.neon启用后,OperandsInArithmeticDivisionRule会对每个除法表达式做操作数类型检查,一旦发现非数值类型就会报告上述标识符。
PHP 语义依据:除法要求数值操作数
从 PHP 语言语义看,除法运算符/期望两个操作数都是数值类型(int或float)。当右侧操作数是bool、null、array、object等非数值类型时:
- 在非严格模式下,PHP 可能尝试进行弱类型转换,产生不符合预期的结果;
- 在严格模式(
declare(strict_types = 1))下,则可能直接抛出TypeError。
即便某些情况下bool能被运行时"凑合"转换成数字(如true转 1、false转 0),代码的意图也几乎肯定是错误的——把布尔值放进除法运算,通常是参数类型设计错误或变量使用错误,这正是 strict-rules 要在静态分析阶段拦截它的原因:指向"会导致崩溃、根本不会按预期执行、或与开发者意图不符"的代码。
如何修复:两种由文档给出的标准方案
方案一:修正类型声明,让右操作数真正是数值
最直接的修复是修复 bug 本身——把参数类型从bool改为数值类型:
<?php declare(strict_types = 1); -function doFoo(int $numerator, bool $flag): void +function doFoo(int $numerator, float $divisor): void { - $result = $numerator / $flag; + $result = $numerator / $divisor; }方案二:在使用前显式转换类型
如果业务上确实需要传入一个布尔值参与运算(这种情况应当非常罕见),则在除法之前显式转换,让类型信息与运行时行为保持一致:
<?php declare(strict_types = 1); function doFoo(int $numerator, bool $flag): void { - $result = $numerator / $flag; + $result = $numerator / (int) $flag; }注意这里使用的是显式强转(int),而不是依赖 PHP 的隐式弱类型转换——显式转换表达了开发者的真实意图,也让 PHPStan 能推导出/右侧现在是int,从而消除该错误。
修复顺序的通用建议
从本仓库 website/errors/CLAUDE.md 对错误文档写作规范的约定来看,推荐按以下优先级修复这类错误:
- 修复实际 bug(把参数类型改对);
- 使用原生 PHP 类型声明收窄类型;
- 使用 PHPDoc 类型(
@param、@return、@var)收窄类型; - 在函数体内进行类型收窄;
- 如果规则可配置,再考虑调整 PHPStan 配置。
对div.rightNonNumeric而言,前两条即"改参数类型 / 显式强转"通常已足够。
同类检查:一套完整的"运算数必须为数值"规则家族
div.rightNonNumeric并不是孤例。在 website/errors 目录下,可以找到一整套结构完全相同的姊妹文档,它们共同构成 strict-rules 的"算术运算数数值性"检查家族:
| 运算符 | 左侧检查 | 右侧检查 |
|---|---|---|
除法/ | div.leftNonNumeric.md | div.rightNonNumeric(本文) |
取模% | mod.leftNonNumeric.md | mod.rightNonNumeric |
加法+ | plus.leftNonNumeric | plus.rightNonNumeric |
减法- | minus.leftNonNumeric | minus.rightNonNumeric |
乘法* | mul.leftNonNumeric | mul.rightNonNumeric |
幂运算** | pow.leftNonNumeric | pow.rightNonNumeric |
例如 mod.leftNonNumeric.md 明确写到:"只有int和float类型应当用于算术运算",这与本文档的核心结论完全一致。当你为%、+、-、*、**的某个操作数传入了bool、null、array、object等类型时,PHPStan 同样会报告对应的*NonNumeric标识符,修复思路与本文完全相同:改对类型,或者在使用前显式转换。
如何在你的项目中使用错误标识符
错误标识符的价值在于:你可以不依赖错误消息文本,而是通过稳定的标识符来精确配置忽略规则。例如在phpstan.neon中只忽略特定位置的div.rightNonNumeric,而保留其它位置的同类错误:
parameters: ignoreErrors: - identifier: div.rightNonNumeric path: legacy/legacy_calculation.php也可以把div.rightNonNumeric等标识符整体加入基线(baseline),方便团队逐步清理存量代码。由于该标识符ignorable: true,所有上述忽略方式都受支持。
小结
div.rightNonNumeric由phpstan/phpstan-strict-rules的OperandsInArithmeticDivisionRule规则报告,用于捕获除法右操作数非数值(bool、null、array、object等)的代码;- 这类代码在运行时可能产生意外结果,严格模式下甚至抛出
TypeError,属于"基本可以确定是逻辑错误"的高置信度警告; - 标准修复方式是修正类型声明或使用前显式强转(如
(int)); - 它属于 strict-rules 覆盖
+、-、*、/、%、**六个运算符的*NonNumeric规则家族,左侧/右侧各有一个对应标识符,可参考 div.leftNonNumeric.md 等姊妹文档交叉查阅; - 通过
identifier: div.rightNonNumeric可以在ignoreErrors或基线中精确配置忽略范围。
想让代码库中的算术运算更健壮,直接启用phpstan/phpstan-strict-rules即可,这一族规则会自动开始工作,把"拿布尔值做除法"这类隐性 bug 拦截在运行之前。
【免费下载链接】phpstanPHP Static Analysis Tool - discover bugs in your code without running it!项目地址: https://gitcode.com/gh_mirrors/ph/phpstan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考