☰
ergebnis/phpstan-rules 版本演进全解析:从 0.1.0 到 2.14.0 的 PHPStan 扩展规则集
2026/10/15 21:25:16 网站建设 项目流程
  • 开发工具

【免费下载链接】php-file-iterator

FilterIterator implementation that filters files based on a list of suffixes, prefixes, and other exclusion criteria.

项目地址:https://gitcode.com/gh_mirrors/ph/php-file-iterator
点击查看免费下载

本篇以ergebnis/phpstan-rules的完整变更记录(CHANGELOG.md)为核心骨架,结合其rules.neon参数定义与源码实现,系统梳理这套 PHPStan 扩展规则集从 0.1.0 到 2.14.0 的全部演进脉络:每一条规则何时引入、哪些参数可供配置、PHP 版本与 phpstan/phpstan 依赖如何变迁,以及 0.14.0 那次从Localheinz\PHPStan迁移到Ergebnis\PHPStan的 breaking change 该如何平滑升级。读完你将掌握该扩展的完整规则清单、配置语法(ergebnis参数段)、错误标识符体系,并能在自己的phpstan.neon中精准启停这些规则。作为实例,仓库根目录的 phpstan.neon 与 tools/.phpstan/composer.json 展示了它在 php-file-iterator 项目中的真实落地方式。

一、这份变更记录在讲什么

ergebnis/phpstan-rules是一套面向 PHPStan 的规则扩展包(type: phpstan-extension),通过composer.json的extra.phpstan.includes自动加载rules.neon,为本就强大的 PHPStan 追加一批"编码风格与设计约束"层面的规则。它要求phpstan/phpstan:^2.1.35,支持 PHP 7.4 ~ 8.6 多个大版本(详见 composer.lock 中该包依赖声明)。

本仓库(phpunit/php-file-iterator)将其作为require-dev依赖锁定在2.14.0(见 tools/.phpstan/composer.json 与 composer.lock),并搭配phpstan/phpstan-strict-rules与phpstan/extension-installer使用,PHPStan 分析入口为 tools/phpstan。

变更记录本身遵循两份业界规范:

  • Keep a Changelog:按Unreleased+ 版本号分节,每节内部再按Added(新增)、Changed(变更)、Fixed(修复)、Removed(移除)分类;
  • Semantic Versioning(语义化版本):0.x为预发布阶段,1.0.0起承诺向后兼容,2.0.0携带破坏性变更。每个版本条目都附有与前一个版本的 diff 链接,方便审计具体改动。

二、规则全景:从 0.1.0 到 2.14.0 的演进时间线

整套规则的演进可以归纳为五条主题线,下面按主题重组变更记录,并保留版本与引入顺序。

1. 类与继承约束(Classes / Methods)

版本规则/变更说明
0.1.0Classes\AbstractOrFinalRule非匿名类既非abstract也非final时报错
0.2.0Classes\FinalRule非匿名类必须final;构造函数增加$excludeClassNames白名单参数
0.5.0参数allowAbstractClasses、classesNotRequiredToBeAbstractOrFinal允许配置FinalRule;AbstractOrFinalRule行为并入FinalRule后被移除,且构造函数默认值被删除(配置必须显式给出)
0.7.0Classes\NoExtendsRule继承未允许的类时报错;0.7.1 起内置一组"默认允许被继承"的类
0.9.0 / 1.0.0FinalRule忽略 Doctrine 实体先忽略注解式实体(@ORM\Mapping\Entity),1.0.0 起也忽略带Doctrine\ORM\Mapping\Entity属性的实体
0.15.0Classes\PHPUnit\Framework\TestCaseWithSuffixRule继承PHPUnit\Framework\TestCase的具体类必须以Test结尾
0.13.0Methods\PrivateInFinalClassRulefinal类中的protected方法若可降级为private则报错;2.5.1 起忽略匿名类、trait 中继承来的protected方法,以及被 PHPUnit 属性/注解要求为protected的方法
0.12.0Methods\FinalInAbstractClassRuleabstract类中具体的public/protected方法必须final;0.15.1 起允许抽象类中存在非final的public构造函数
2.10.0Methods\InvokeParentHookMethodRule覆写父类 hook 方法时若未按预期顺序调用父类实现则报错,行为通过hookMethods参数定义

2. 参数与类型声明约束(Closures / Functions / Methods)

  • 0.3.0 批量引入:Functions\NoNullableReturnTypeDeclarationRule、Methods\NoNullableReturnTypeDeclarationRule、Closures\NoParameterWithNullDefaultValueRule、Closures\NoNullableReturnTypeDeclarationRule、Functions\NoParameterWithNullDefaultValueRule、Methods\NoParameterWithNullDefaultValueRule、Closures\NoParameterWithNullableTypeDeclarationRule、Functions\NoParameterWithNullableTypeDeclarationRule、Methods\NoParameterWithNullableTypeDeclarationRule。
  • 0.5.0:新增Methods\NoConstructorParameterWithDefaultValueRule,禁止类与匿名类的构造函数参数带默认值。
  • 0.12.0:新增Methods\NoParameterWithContainerTypeDeclarationRule,禁止方法参数类型声明为已知的依赖注入容器或服务定位器(默认Psr\Container\ContainerInterface,可通过interfacesImplementedByContainers扩展)。
  • 2.0.0:新增methodsAllowedToUseContainerTypeDeclarations参数,白名单内的方法名允许使用容器类型声明。
  • 2.7.0:新增Closures\NoParameterPassedByReferenceRule、Functions\NoParameterPassedByReferenceRule、Methods\NoParameterPassedByReferenceRule(禁止参数按引用传递)以及Functions\NoReturnByReferenceRule、Methods\NoReturnByReferenceRule(禁止按引用返回)。
  • 2.5.2:上述 6 条 nullable 相关规则补强——能识别null以错误大小写(如Null)或相对于根命名空间引用的情况。

3. 表达式与语句约束(Expressions / Statements / CallLikes)

  • 0.11.0 批量引入:Expressions\NoEmptyRule(empty())、Expressions\NoEvalRule(eval())、Expressions\NoErrorSuppressionRule(@错误抑制)、Expressions\NoCompactRule(compact())、Statements\NoSwitchRule(switch)。同时要求nikic/php-parser:^4.2.3、phpstan/phpstan:~0.11.15。
  • 0.8.0:Expressions\NoIssetRule(isset()),0.8.1 修复了该规则未被真正启用的问题。
  • 2.8.0:新增Expressions\NoAssignByReferenceRule,禁止变量按引用赋值。
  • 2.9.0:新增CallLikes\NoNamedArgumentRule,禁止以命名参数(named argument)调用匿名函数、函数或方法。
  • 2.0.0:Expressions\NoEmptyRule被移除(breaking change),empty()不再由本扩展约束。
  • 2.10.4 / 2.10.5:NoNamedArgumentRule持续修复——支持变量表达式上的静态调用、invokable 调用、属性上的 callable、变量类名构造函数;对无法解析的调用退化为通用错误消息,仅对已知调用给出精确描述。

4. 文件级约束(Files)

  • 0.11.0:Files\DeclareStrictTypesRule,PHP 文件缺少declare(strict_types=1)时报错;0.14.3 起忽略首行为 shebang 的情况。
  • 2.13.0:Files\NoPhpstanIgnoreRule,发现@phpstan-ignore、@phpstan-ignore-line、@phpstan-ignore-next-line标签时报错,强制"修掉错误或使用 baseline,而不是就地忽略"。

5. 错误消息与标识符演进

  • 0.4.0:移除错误消息中的双引号、统一方法/函数/参数名的措辞与位置,使输出风格与 phpstan/phstan 自身错误消息一致。
  • 2.5.0:为每条规则引入机器可读的错误标识符(error identifier);2.5.1 起规则通过 builder 正式返回带标识符的错误,2.6.1 修复NoParameterWithNullableTypeDeclarationRule使用了不正确的标识符,2.10.2 为InvokeParentHookMethodRule重命名了标识符。

三、三个关键里程碑的深度解读

1. 0.14.0:命名空间迁移与参数段重构(breaking change)

这是 0.x 阶段最重要的破坏性版本,包含两项必须手工迁移的变更:

其一,vendor 命名空间从Localheinz更名为Ergebnis。官方给出的三步升级命令:

composer remove localheinz/phpstan-rules composer require ergebnis/phpstan-rules

再替换源码与配置中出现过的Localheinz\PHPStan前缀:

find . -type f -exec sed -i '.bak' 's/Localheinz\\PHPStan/Ergebnis\\PHPStan/g' {} \;

最后清理备份文件:

find -type f -name '*.bak' -delete

其二,参数从全局parameters段移入ergebnis段。此前phpstan.neon的写法是:

parameters: allowAbstractClasses: true classesAllowedToBeExtended: [] classesNotRequiredToBeAbstractOrFinal: [] interfacesImplementedByContainers: - Psr\Container\ContainerInterface

0.14.0 之后这些参数必须全部嵌套到ergebnis之下(防止与 PHPStan 全局参数命名冲突):

parameters: - allowAbstractClasses: true - classesAllowedToBeExtended: [] - classesNotRequiredToBeAbstractOrFinal: [] - interfacesImplementedByContainers: - - Psr\Container\ContainerInterface + ergebnis: + allowAbstractClasses: true + classesAllowedToBeExtended: [] + classesNotRequiredToBeAbstractOrFinal: [] + interfacesImplementedByContainers: + - Psr\Container\ContainerInterface

同版本还修复了composer.json中不当的replace配置(0.14.1)、恢复了 PHP 7.1 支持(0.14.2)、并借 0.10.0 的parametersSchema保证了与bleedingEdge.neon的兼容性。

2. 1.0.0:正式稳定

1.0.0 起支持phpstan/phpstan:^1.0.0并放弃非稳定版本;同时FinalRule不再对带Doctrine\ORM\Mapping\Entity属性的非 final 类报错。此后0.x阶段结束,进入语义化版本承诺期。

3. 2.0.0:面向 PHPStan 2.x 的大版本

2.0.0 是一次集中的破坏性变更:

  • 移除 PHP 7.2 / 7.3 / 7.4 支持,新增 PHP 8.2 支持;
  • 新增methodsAllowedToUseContainerTypeDeclarations参数(允许使用容器类型声明的方法名列表);
  • 新增"禁用任意规则"的能力(配合后文enabled: false使用);
  • 支持 nullable union types;
  • 移除Expressions\NoEmptyRule。

此后的 2.x 演进主线是"扩平台 + 加规则":2.1.0 丢弃 PHP 8.0、支持 PHP 8.3;2.2.0 允许nikic/php-parser:^5.0.0;2.3.0/2.4.0 支持 PHP 8.4;2.5.0 支持 PHP 7.4 与 8.0 并移除对nikic/php-parser的依赖;2.6.0 支持phpstan/phpstan:^2.0.0;2.11.0/2.12.0 支持 PHP 8.5;2.14.0 允许安装于 PHP 8.6。依赖上,2.9.0 要求phpstan/phpstan:^2.1.8,2.13.0 提高到^2.1.35。

四、当前规则清单与完整配置参数(依据 rules.neon)

包内 rules.neon 是配置中枢:conditionalTags依据各规则的enabled参数决定是否注册为 PHPStan 规则;parameters给出全部默认值;parametersSchema定义参数结构校验;services完成依赖注入。

当前 2.14.0 共注册 25 条规则,全部默认启用(顶层ergebnis.allRules: true):

规则类规则关键参数(默认值)
CallLikes\NoNamedArgumentRule禁止命名参数调用enabled
Classes\FinalRule类必须 finalenabled、allowAbstractClasses(true)、classesNotRequiredToBeAbstractOrFinal([])
Classes\NoExtendsRule禁止继承未许可类enabled、classesAllowedToBeExtended([])
Classes\PHPUnit\Framework\TestCaseWithSuffixRule测试类须以 Test 结尾enabled
Closures\NoNullableReturnTypeDeclarationRule闭包禁止可空返回类型enabled
Closures\NoParameterPassedByReferenceRule闭包禁止按引用传参enabled
Closures\NoParameterWithNullableTypeDeclarationRule闭包禁止可空参数类型enabled
Expressions\NoAssignByReferenceRule禁止按引用赋值enabled
Expressions\NoCompactRule禁止compact()enabled
Expressions\NoErrorSuppressionRule禁止@抑制错误enabled
Expressions\NoEvalRule禁止eval()enabled
Expressions\NoIssetRule禁止isset()enabled
Files\DeclareStrictTypesRule必须declare(strict_types=1)enabled
Files\NoPhpstanIgnoreRule禁止@phpstan-ignore*标签enabled
Functions\NoNullableReturnTypeDeclarationRule函数禁止可空返回类型enabled
Functions\NoParameterPassedByReferenceRule函数禁止按引用传参enabled
Functions\NoParameterWithNullableTypeDeclarationRule函数禁止可空参数类型enabled
Functions\NoParameterWithNullDefaultValueRule函数参数禁止null默认值enabled
Functions\NoReturnByReferenceRule禁止按引用返回enabled
Methods\FinalInAbstractClassRule抽象类具体方法须 finalenabled
Methods\InvokeParentHookMethodRulehook 方法须按序调用父类实现enabled、hookMethods([])
Methods\NoConstructorParameterWithDefaultValueRule构造参数禁止默认值enabled
Methods\NoNullableReturnTypeDeclarationRule方法禁止可空返回类型enabled
Methods\NoParameterPassedByReferenceRule方法禁止按引用传参enabled
Methods\NoParameterWithContainerTypeDeclarationRule方法禁止容器类型声明enabled、interfacesImplementedByContainers([Psr\Container\ContainerInterface])、methodsAllowedToUseContainerTypeDeclarations([])
Methods\NoParameterWithNullableTypeDeclarationRule方法禁止可空参数类型enabled
Methods\NoParameterWithNullDefaultValueRule方法参数禁止null默认值enabled
Methods\NoReturnByReferenceRule方法禁止按引用返回enabled
Methods\PrivateInFinalClassRulefinal 类中 protected 应降为 privateenabled
Statements\NoSwitchRule禁止switchenabled

(其中Closures\NoParameterWithNullDefaultValueRule与Expressions\NoEmptyRule已不在当前清单中:前者未出现在rules.neon的 conditionalTags 内,后者在 2.0.0 被移除。)

invokeParentHookMethod.hookMethods的 schema 定义较为独特,每个元素包含四个字段(依据parametersSchema):

  • className(string):hook 方法所属父类名;
  • methodName(string):hook 方法名;
  • hasContent("no"或"yes"):父类实现是否有内容;
  • invocation("any"、"first"或"last"):子类应在何时调用父类实现。

配置示例:按需启停规则

启用全部规则即可省略ergebnis段(默认allRules: true);只启用部分规则则把allRules设为false并逐个声明:

parameters: ergebnis: allRules: false final: enabled: true allowAbstractClasses: false classesNotRequiredToBeAbstractOrFinal: - PHPUnit\Framework\TestCase privateInFinalClass: enabled: true noExtends: enabled: true classesAllowedToBeExtended: - Symfony\Component\EventDispatcher\EventSubscriberInterface

五、错误标识符体系

自 2.5.0 引入、2.5.1 起随错误正式返回的错误标识符(error identifier),统一形如ergebnis.<ruleName>。定义集中在 src/ErrorIdentifier.php:final()→ergebnis.final、noPhpstanIgnore()→ergebnis.noPhpstanIgnore、privateInFinalClass()→ergebnis.privateInFinalClass、noNamedArgument()→ergebnis.noNamedArgument等(toString()方法负责拼接前缀,见 src/ErrorIdentifier.php#L138-L144)。

标识符的价值在于:它允许在 PHPStan 的reportUnmatchedIgnoredErrors场景下精确匹配/忽略特定规则、在 CI 中按标识符聚合统计错误,也让@phpstan-ignore ergebnis.noCompact这类带标识符的定向忽略成为可能——当然,NoPhpstanIgnoreRule会禁止你这么做(详见下一节)。

六、源码剖析与在本仓库中的实际落地

NoPhpstanIgnoreRule 的实现方式

src/Files/NoPhpstanIgnoreRule.php 是 2.13.0 新增规则的代表性实现:它实现了PHPStan\Rules\Rule<FileNode>(getNodeType()返回FileNode::class,见 L29-L32),用PhpParser\NodeFinder遍历文件全部节点,收集每个节点的注释并按行匹配正则@phpstan-ignore(-line|-next-line)?(见 L49);一旦命中,就报出提示"应修复错误或改用 baseline,而不是用@phpstan-ignore就地忽略"(消息文本见 L55-L58),并通过ErrorIdentifier::noPhpstanIgnore()携带标识符、nonIgnorable()标记为不可忽略。2.13.1 修复了它遍历节点不全的问题,2.14.0 又修正了Functions\NoParameterPassedByReferenceRule的错误标识符。

php-file-iterator 中的真实配置

仓库根目录的 phpstan.neon 是这套扩展在真实项目中的配置范本:

parameters: level: 10 paths: - src - tests/unit strictRules: allRules: false booleansInConditions: true closureUsesThis: true disallowedBacktick: true disallowedEmpty: true disallowedImplicitArrayCreation: true disallowedLooseComparison: true disallowedShortTernary: true illegalConstructorMethodCall: true matchingInheritedMethodNames: true noVariableVariables: true numericOperandsInArithmeticOperators: true overwriteVariablesWithLoop: true requireParentConstructorCall: true strictFunctionCalls: true switchConditionsMatchingType: true uselessCast: true ergebnis: allRules: false final: enabled: true privateInFinalClass: enabled: true includes: - phar://phpstan.phar/conf/bleedingEdge.neon

可见该项目的做法是:分析等级拉到level: 10并叠加bleedingEdge.neon(这正是 0.10.0 补上parametersSchema后得以兼容的场景),同时并行使用phpstan-strict-rules与ergebnis/phpstan-rules两套扩展;对ergebnis只显式启用final与privateInFinalClass两条最符合该库"类设计收敛"诉求的规则,其余规则保持关闭(allRules: false)。依赖侧,tools/.phpstan/composer.json 声明ergebnis/phpstan-rules: ^2.14.0、phpstan/phpstan: ^2.2.17、phpstan/extension-installer: ^1.4.3(后者自动激活rules.neon的 include),并由 composer.lock 锁定到 2.14.0。

七、升级与维护建议

  • 版本策略:以 SemVer 为准。2.x内部的小版本升级通常安全(新增规则默认启用可能带来新报错,建议升级后先跑一遍全量分析);3.0.0如出现,需重点核对规则移除与参数结构变更。
  • 0.14.0 之前的老用户:参照第三节的迁移命令,完成命名空间替换与参数移入ergebnis段两步操作。
  • 新增规则默认全开:allRules: true意味着每次升级都可能引入新的约束(如 2.13.0 的NoPhpstanIgnoreRule会立刻对既有@phpstan-ignore标签报错)。若担心波动,可先设allRules: false再逐个enabled: true灰度。
  • 与 strict-rules 的取舍:ergebnis/phpstan-rules偏"设计约束",phpstan/phpstan-strict-rules偏"严格语义",两者互补;php-file-iterator 的 phpstan.neon 就是两者同开的参考配置。

八、结语

从 0.1.0 的单一AbstractOrFinalRule到 2.14.0 的 25 条规则、错误标识符体系、allRules总开关与 PHP 8.6 支持,ergebnis/phpstan-rules的变更记录完整展现了"类设计收敛 → 类型声明纪律 → 表达式/语句禁令 → 文件级规范"这条规则谱系。对使用者而言,最有价值的不是背诵每条规则,而是掌握 rules.neon 这一配置中枢:用allRules控制总体范围、用各规则的enabled与专项参数微调边界、用错误标识符对接 CI 与 IDE。本文的版本对照表与配置示例可直接复制到你的phpstan.neon中按需裁剪。

  • 开发工具

【免费下载链接】php-file-iterator

FilterIterator implementation that filters files based on a list of suffixes, prefixes, and other exclusion criteria.

项目地址:https://gitcode.com/gh_mirrors/ph/php-file-iterator
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询