PHP-CS-Fixer 的 array_syntax 规则:统一 PHP 数组声明的 long/short 语法
【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址: https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
array_syntax是 PHP-CS-Fixer 中用于统一 PHP 数组声明语法的核心规则,它可以在array(...)(long 语法)与[...](short 语法)之间按配置自动转换。本文以该规则的官方文档为基础,结合仓库中的 ArraySyntaxFixer 源码 与其 官方测试用例,完整讲解配置参数、运行效果、底层 token 级实现原理、优先级协作方式及所属规则集,帮助你在项目落地统一的数组书写风格。
规则概述
该规则的官方定义只有一句话:"PHP arrays should be declared using the configured syntax."(PHP 数组应使用所配置的语法来声明)。换句话说,它不关心你的项目到底该用array()还是[],而是保证全仓库只存在一种被选定的写法,从而消除同一代码库内两种语法混用带来的风格不一致。
该规则属于可配置(CONFIGURABLE)规则,唯一的配置项是syntax,因此你可以在不同项目、不同目录下定制各自的数组书写风格。
配置参数:syntax
| 配置项 | 说明 | 允许值 | 默认值 |
|---|---|---|---|
syntax | 使用 long 还是 short 数组语法 | 'long'、'short' | 'short' |
'short':将array(1,2)转换为[1,2],这是默认行为,也符合现代 PHP(5.4+)的主流编码风格。'long':将[1,2]转换回array(1,2),适合需要兼容旧代码风格或团队规范强制 long 语法的场景。
从源码看,配置解析位于 ArraySyntaxFixer.php 的createConfigurationDefinition()中,通过FixerOptionBuilder构建:
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder('syntax', 'Whether to use the `long` or `short` array syntax.')) ->setAllowedValues(['long', 'short']) ->setDefault('short') ->getOption(), ]); }setAllowedValues(['long', 'short'])意味着传入其他任何值都会触发配置校验错误;而setDefault('short')说明即使你只写'array_syntax' => true而不提供选项,也会按 short 语法处理。测试 testInvalidConfiguration 还验证了:传入不存在的选项(如['a' => 1])会抛出InvalidFixerConfigurationException,并提示"Defined options are: 'syntax'"。
运行效果示例
官方文档给出了两个 diff 形式的示例。
示例 1:默认配置(syntax未设置,即'short')
--- Original +++ New <?php -array(1,2); +[1,2];示例 2:配置为['syntax' => 'long']
--- Original +++ New <?php -[1,2]; +array(1,2);在配置文件中启用
推荐通过项目根目录的.php-cs-fixer.php配置文件声明规则(若需要全局默认值,可在.php-cs-fixer.dist.php中设置):
<?php return (new PhpCsFixer\Config()) ->setRules([ // 使用默认的 short 语法:把 array(...) 统一转为 [...] 'array_syntax' => true, // 或者显式指定为 long 语法 'array_syntax' => ['syntax' => 'long'], ]) ->setFinder( (new PhpCsFixer\Finder()) ->in(__DIR__.'/src') );配置完成后即可执行php php-cs-fixer fix(或vendor/bin/php-cs-fixer fix)让规则生效;若只想预览改动而不写入文件,可加上--dry-run --diff参数查看 diff。
源码实现原理:token 级的双向转换
array_syntax的修复逻辑完全构建在 PHP-CS-Fixer 的 Tokenizer 之上,核心代码在 ArraySyntaxFixer.php。
候选 token 的确定。规则根据配置提前决定"要寻找哪种语法的 token":
private function resolveCandidateTokenKind(): void { $this->candidateTokenKind = 'long' === $this->configuration['syntax'] ? CT::T_ARRAY_BRACKET_OPEN : \T_ARRAY; }- 目标是 short 语法时,寻找
T_ARRAY(即array关键字); - 目标是 long 语法时,寻找
CT::T_ARRAY_BRACKET_OPEN(即[,这里使用了自定义 token 类型 CT 来区分"数组左括号"与"下标访问左括号")。
short 方向(array(...)→[...])。找到T_ARRAY后,向后定位(,再用findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS, $openIndex)找到匹配的),把这一对括号分别替换为[和],最后清除array关键字 token:
$tokens[$openIndex] = new Token([CT::T_ARRAY_BRACKET_OPEN, '[']); $tokens[$closeIndex] = new Token([CT::T_ARRAY_BRACKET_CLOSE, ']']); $tokens->clearTokenAndMergeSurroundingWhitespace($index);long 方向([...]→array(...))。找到CT::T_ARRAY_BRACKET_OPEN后,用findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_BRACKET, $index)找到匹配的],将括号对替换为(与),并在原位置插入array关键字 token:
$tokens[$index] = new Token('('); $tokens[$closeIndex] = new Token(')'); $tokens->insertAt($index, new Token([\T_ARRAY, 'array']));批量扫描方式。applyFix()采用从后向前遍历 token 的循环(for ($index = $tokens->count() - 1; 0 <= $index; --$index)),自后向前处理可以避免插入/替换 token 导致索引偏移影响后续处理。修复会递归覆盖嵌套数组、三元表达式内的数组、函数参数等所有位置,例如[[[]]]可被完整地双向转换。
优先级:与相邻规则的协作顺序
array_syntax的优先级为37,在源码注释中明确声明:
Must run before BinaryOperatorSpacesFixer, NoWhitespaceInEmptyArrayFixer, SingleSpaceAfterConstructFixer, SingleSpaceAroundConstructFixer, TernaryOperatorSpacesFixer.
这意味着它必须先于上述空格/括号类规则执行,原因很直观:array( )与[ ]在转换前后括号形态变化,而空白处理规则依赖最终的括号形态。仓库用集成测试固化了这种协作,例如 array_syntax,binary_operator_spaces.test 验证了输入$a = array ();在array_syntax(short)与binary_operator_spaces(赋值号单空格)同时启用时输出为$a = [];。同类优先级测试还包括array_syntax与no_whitespace_in_empty_array、single_space_after_construct、single_space_around_construct、ternary_operator_spaces的组合(见 tests/Fixtures/Integration/priority 目录)。
边界情况:什么不会被改写
并不是所有[]都会被当成数组声明。从官方测试用例(ArraySyntaxFixerTest.php)可以看出,即使配置为syntax => 'long',以下写法保持原样、不会被转换:
- 数组追加与下标访问:
$x[] = 1;、$x[ ] = 1;、$x[2] = 1;、$x["a"] = 1; - 函数返回值下标:
$x = func()[$x]; - 字符串下标:
$x = "foo"[$x]; - 字符串插值中的下标:
$text = "foo ${aaa[123]} bar $bbb[0] baz"; foreach中的数组解构:foreach ($array as [$x, $y]) {}
原因在于这些[在 tokenizer 中并不是CT::T_ARRAY_BRACKET_OPEN类型的"数组声明左括号",规则通过候选 token 类型天然规避了误伤。
所属规则集
官方文档列出了该规则参与的全部规则集(分别位于 doc/ruleSets 目录):
| 规则集 | 备注 |
|---|---|
| @PER | 已废弃(deprecated) |
| @PER-CS | |
| @PER-CS2.0 | 已废弃 |
| @PER-CS2x0 | |
| @PER-CS3.0 | 已废弃 |
| @PER-CS3x0 | |
| @PHP5x4Migration | |
| @PHP7x0Migration | |
| @PHP7x1Migration | |
| @PHP7x3Migration | |
| @PHP7x4Migration | |
| @PHP8x0Migration | |
| @PHP8x1Migration | |
| @PHP8x2Migration | |
| @PHP8x3Migration | |
| @PHP8x4Migration | |
| @PHP8x5Migration | |
| @PHP54Migration 至 @PHP85Migration 系列 | 旧命名,均已废弃 |
| @PhpCsFixer | |
| @Symfony |
规则集层面的关键点:
- 在 PERCS2x0Set.php 中,
array_syntax => true随@PER-CS2x0启用,意味着遵循 PER Coding Style 2.0 的项目会自动获得 short 数组语法约束; - 在 PHP5x4MigrationSet.php 中,
array_syntax是迁移集唯一启用的规则——这正对应 PHP 5.4 引入[]short 数组语法的历史事实,迁移到 PHP 5.4+ 时该规则会自动把所有array()改为[]; - 更高版本的 PHP 迁移集(如
@PHP7x0Migration等)通过继承链(AbstractMajorMinorDeprecationSetDefinition)向下包含该规则,所以数组语法统一贯穿整个迁移规则集体系。
测试保障与向后兼容承诺
官方测试类 ArraySyntaxFixerTest.php 是该项目"向后兼容承诺"的一部分,官方文档明确说明:"The test class defines officially supported behaviour. Each test case is a part of our backward compatibility promise."(测试类定义了官方支持的行为,每个测试用例都是向后兼容承诺的一部分)。
测试通过provideFixCases()数据提供器覆盖了大量场景,包括:默认配置、显式long/short、空数组、带空格括号、字符串元素、三元表达式嵌套数组、函数调用实参、多层嵌套([[[]]])、函数默认参数(function(array $foo = []))、数组字面量直接下标([1, 2][0])以及前文所述的各类边界情况。这意味着只要你的代码处于这些被覆盖的形态,规则的行为就是有测试背书、可放心依赖的。
小结与使用建议
array_syntax是一个"小而关键"的规则:它只做一件事——统一数组声明语法,但通过 token 级实现、优先级设计与测试保障,做到了安全、可靠、可配置。实际项目落地时可以参考以下思路:
- 新项目:直接启用
'array_syntax' => true(short 语法),或直接使用@PER-CS2x0/@Symfony等已包含该规则的规则集; - 旧项目迁移:若代码量较大,建议先用
--dry-run --diff预览全部改动,确认没有foreach解构、字符串插值等边界场景被误伤; - 反向约束:若团队规范要求 long 语法(例如强兼容 PHP 5.3 的遗留系统),配置
['syntax' => 'long']即可反向统一; - 配合验证:修改规则后运行
vendor/bin/php-cs-fixer fix --dry-run --diff,并结合仓库内的集成测试理解其与其他空格类规则的协作结果。
参考与深入阅读
- 规则官方文档:doc/rules/array_notation/array_syntax.rst
- 修复器实现:src/Fixer/ArrayNotation/ArraySyntaxFixer.php
- 官方测试:tests/Fixer/ArrayNotation/ArraySyntaxFixerTest.php
- 优先级集成测试:tests/Fixtures/Integration/priority 目录下
array_syntax,*系列文件 - 规则集定义:src/RuleSet/Sets/PERCS2x0Set.php、src/RuleSet/Sets/PHP5x4MigrationSet.php
【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址: https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考