PHP-CS-Fixer 规则集解析:@PHPUnit100Migration:risky 的废弃迁移机制与 PHPUnit 10 兼容实战
2026/9/23 4:31:33 网站建设 项目流程
  • 开发工具
  • 代码质量
  • 静态分析
  • Lint
  • 格式化

【免费下载链接】PHP-CS-Fixer

A tool to automatically fix PHP Coding Standards issues

项目地址:https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
点击查看免费下载

@PHPUnit100Migration:risky是 PHP-CS-Fixer 内置的迁移规则集,用于自动改进测试代码以兼容 PHPUnit 10.0。本文基于 PHPUnit100MigrationRisky.rst 展开,结合仓库源码说明其废弃状态、命名迁移机制(10010x0)、风险等级判定规则,以及实际使用@PHPUnit10x0Migration:risky时应了解的规则构成与配置要点。

规则集定位:为 PHPUnit 10.0 准备测试代码

@PHPUnit100Migration:risky的核心使命非常明确——改进测试代码以兼容 PHPUnit 10.0。它是 PHP-CS-Fixer 众多迁移规则集(Migration Rule Set)中的一员,与@PHPUnit9x1Migration:risky@PHPUnit10x0Migration:risky@PHPUnit11x0Migration:risky等组成一套面向 PHPUnit 各版本升级的规则集家族。

从仓库源码可以印证这一点。AbstractMigrationSetDefinition.php 中的getDescription()方法会根据规则集名称自动生成描述,其内部为PHPUnit实体预设了tests code(测试代码)作为改进对象,最终拼接出Rules to improve tests code for PHPUnit 10.0 compatibility.这样的描述文案——这正是该规则集文档第一句话的源码出处。

重要警告:该规则集已废弃,将在 4.0 移除

这是阅读本规则集文档时最先需要掌握的信息:@PHPUnit100Migration:risky已被标记为 DEPRECATED,并将在下一个大版本(4.0)中被移除。官方给出的替代方案是:

You should use@PHPUnit10x0Migration:riskyinstead.

也就是说,如果你正在编写新的配置文件或维护现有配置,不要直接使用@PHPUnit100Migration:risky,而应改用@PHPUnit10x0Migration:risky。前者保留在当前版本中仅仅是为了向后兼容,属于过渡性存在。

源码层面的废弃机制

废弃并非仅仅停留在文档层面,源码实现完整支撑了这一设计。规则集类 PHPUnit100MigrationRiskySet.php 本身是一个空类,继承自AbstractMajorMinorDeprecationSetDefinition,后者在 AbstractMajorMinorDeprecationSetDefinition.php 中实现了废弃规则集的核心逻辑:

public function getRules(): array { $newName = Preg::replace('#(\d+)\.?(\d)#', '\1x\2', $this->getName()); return [ $newName => true, ]; } public function getSuccessorsNames(): array { return array_keys($this->getRules()); }

这段代码揭示了两层关键事实:

  1. 废弃规则集是"转发器"getRules()返回的并不是具体的 fixer 规则列表,而是把自身名称经过正则转换后指向新规则集。对@PHPUnit100Migration:risky而言,正则#(\d+)\.?(\d)#会把名称中的100转换为10x0,最终得到['@PHPUnit10x0Migration:risky' => true]——即"使用我,等同于使用新的@PHPUnit10x0Migration:risky"。
  2. 后继者名称机制getSuccessorsNames()返回替代规则集的名称,配合 DeprecatedRuleSetDefinitionInterface.php 定义的getSuccessorsNames(): array契约,让工具链(如 CLI 的警告检测、文档生成器)能够向用户明确提示应当改用哪个新规则集。

类名到规则集名的转换由 AbstractRuleSetDefinition.php 完成:取类名去掉命名空间与Set后缀,再把Risky替换为:risky,于是PHPUnit100MigrationRiskySet就变成了@PHPUnit100Migration:risky

"x" 命名约定的来由

10x0这种带x的命名并非随意为之。从 AbstractMigrationSetDefinition.php 的parseRuleSetName()可以看到,规则集名称通过正则#^@PHPUnit(\d+)x?(\d)Migration.*$#解析出实体(PHPUnit)与主/次版本号(major=10, minor=0)。x表示该规则集面向"该主版本全系列"(10.x 的所有次版本),相比精确到次版本的100命名,10x0的语义更宽泛、更具长期适用性。源码中的@TODO v4注释也表明,当前保留x?的可选匹配正是为了兼容这种新旧命名并存的过渡期。

风险提示:这是 RISKY 规则集

与普通规则集不同,@PHPUnit100Migration:risky(及其后继者@PHPUnit10x0Migration:risky)属于高风险(RISKY)规则集。文档明确警告:

This set contains rules that are risky. Using it may lead to changes in your code's logic and behaviour. Use it with caution and review changes before incorporating them into your code base.

风险规则集意味着其中的 fixer 可能改变代码的逻辑与行为,而非仅仅调整格式。因此:

  • 必须在配置中显式开启,且通常需要配合--allow-risky=yes(或在配置中设置'risky' => true的规则时显式允许)才会生效;
  • 使用前应充分理解每条规则的具体行为,合并前务必人工审查 diff;
  • 从源码看,AbstractRuleSetDefinition.php 的isRisky()方法以类名是否包含Risky判定规则集风险属性,机制简单直接。

替换规则集的实际构成:@PHPUnit10x0Migration:risky

既然官方建议改用@PHPUnit10x0Migration:risky,那么了解它实际包含哪些规则就至关重要。在 PHPUnit10x0MigrationRiskySet.php 中可以看到其完整的规则清单:

public function getRules(): array { return [ '@PHPUnit9x1Migration:risky' => true, 'php_unit_data_provider_static' => ['force' => true], ]; }

即该规则集包含两部分:

  1. @PHPUnit9x1Migration:risky:嵌套引用的另一个迁移规则集,负责从 PHPUnit 9.1 迁移过来的相关修复;
  2. php_unit_data_provider_static(配置['force' => true]:将数据提供者方法强制改为static

核心规则详解:php_unit_data_provider_static

php_unit_data_provider_static是本规则集唯一的独立 fixer 规则,详细文档见 php_unit_data_provider_static.rst,其对应实现为 PhpUnitDataProviderStaticFixer.php,测试类为 PhpUnitDataProviderStaticFixerTest.php。

规则作用

数据提供者(Data Provider)方法必须是static的。这是 PHPUnit 10 的硬性要求之一:从 PHPUnit 10 开始,非静态的 data provider 将触发弃用警告直至报错,因此迁移到 PHPUnit 10 前必须把所有@dataProvider引用的方法改为静态方法。

可配置项:force

配置项类型默认值说明
forceboolfalse是否强制将数据提供者改为静态,即使其内部存在动态类调用(如$this->...
  • force => false(默认):仅当方法体不依赖$this(可以安全静态化)时才添加static关键字,避免引入运行时错误;
  • force => true:无条件添加static关键字。文档特别警告:这可能引入致命错误using $this when not in object context,你需要手动把方法体内的动态调用($this->method())改为静态调用(self::method())。

配置示例对比

默认配置(仅安全场景转换):

<?php class FooTest extends TestCase { /** * @dataProvider provideSomethingCases */ public function testSomething($expected, $actual) {} - public function provideSomethingCases() {} + public static function provideSomethingCases() {} }

['force' => true](无条件转换,含$this的方法也会被加static):

<?php class FooTest extends TestCase { /** * @dataProvider provideSomethingCases1 * @dataProvider provideSomethingCases2 */ public function testSomething($expected, $actual) {} - public function provideSomethingCases1() { $this->getData1(); } - public function provideSomethingCases2() { self::getData2(); } + public static function provideSomethingCases1() { $this->getData1(); } + public static function provideSomethingCases2() { self::getData2(); } }

注意第一个方法在force => true下虽然被加上了static,但内部的$this->getData1()会在运行时触发致命错误,这正是"必须人工审查并手动修复"的风险来源。

['force' => false](跳过含$this的方法):

<?php class FooTest extends TestCase { /** * @dataProvider provideSomething1Cases * @dataProvider provideSomething2Cases */ public function testSomething($expected, $actual) {} public function provideSomething1Cases() { $this->getData1(); } - public function provideSomething2Cases() { self::getData2(); } + public static function provideSomething2Cases() { self::getData2(); } }

为何在迁移规则集中默认force => true

从 php_unit_data_provider_static.rst 的 "Rule sets" 一节可以看到,force => true的强配置同时被@PhpCsFixer:risky@PHPUnit10x0Migration:risky@PHPUnit11x0Migration:risky以及(已废弃的)@PHPUnit100Migration:risky采用。原因在于:PHPUnit 10 要求 data provider 必须静态,若不强制转换,含有$this的方法将无法通过 PHPUnit 10 的运行校验;强制转换虽然可能引发瞬时错误,但能保证"一次性暴露所有需要手工修复的点",从而推动彻底完成迁移。

如何在实际项目中应用

虽然@PHPUnit100Migration:risky已废弃,但理解它的用法依然有现实意义——你可以把同样的配置方式迁移到新规则集上。在.php-cs-fixer.php配置文件中启用该迁移:

<?php $finder = PhpCsFixer\Finder::create() ->in(__DIR__.'/tests'); return (new PhpCsFixer\Config()) ->setRiskyAllowed(true) // 必须允许 risky 规则 ->setRules([ '@PHPUnit10x0Migration:risky' => true, ]) ->setFinder($finder);

要点总结:

  1. 必须setRiskyAllowed(true)(或 CLI 加--allow-risky=yes),否则包含 risky 规则的规则集不会生效;
  2. 不要在新配置中写@PHPUnit100Migration:risky,直接使用@PHPUnit10x0Migration:risky;若旧配置仍引用前者,CLI 会基于getSuccessorsNames()给出弃用提示;
  3. 运行前先备份或用版本控制确认改动,因为php_unit_data_provider_staticforce => true下可能生成暂不能运行的代码($this调用),需人工将动态调用改为self::静态调用;
  4. 迁移完成后建议结合 PHPUnit 10 实际运行测试套件验证,而非只依赖格式检查。

关联资源索引

  • 规则集文档:doc/ruleSets/PHPUnit100MigrationRisky.rst、后继者文档 doc/ruleSets/PHPUnit10x0MigrationRisky.rst
  • 废弃转发实现:src/RuleSet/AbstractMajorMinorDeprecationSetDefinition.php
  • 新规则集定义:src/RuleSet/Sets/PHPUnit10x0MigrationRiskySet.php
  • 规则详情:doc/rules/php_unit/php_unit_data_provider_static.rst
  • Fixer 实现与测试:src/Fixer/PhpUnit/PhpUnitDataProviderStaticFixer.php、tests/Fixer/PhpUnit/PhpUnitDataProviderStaticFixerTest.php

总而言之,@PHPUnit100Migration:risky是 PHP-CS-Fixer 面向 PHPUnit 10.0 迁移的历史性规则集,其文档价值在于:既说明了"已废弃、改用@PHPUnit10x0Migration:risky"这一关键事实,也通过源码揭示了废弃规则集如何借助AbstractMajorMinorDeprecationSetDefinition实现向后兼容的转发机制,并展示了 risky 迁移规则集在提升兼容性的同时所伴随的行为变更风险。

  • 开发工具
  • 代码质量
  • 静态分析
  • Lint
  • 格式化

【免费下载链接】PHP-CS-Fixer

A tool to automatically fix PHP Coding Standards issues

项目地址:https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
点击查看免费下载

相关推荐

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

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

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

立即咨询