- 开发工具
- 代码质量
- 静态分析
- Lint
- 格式化
【免费下载链接】PHP-CS-Fixer
A tool to automatically fix PHP Coding Standards issues
导读
本文围绕 PHP-CS-Fixer 仓库中的align_multiline_comment规则展开,它负责强制多行 DocBlock 注释(以及可选的普通多行注释)每一行都必须以星号*开头,并与首行星号对齐,从而符合 PSR-5 关于 DocComment 的书写规范。读完本文,你将掌握该规则的三种comment_type配置(phpdocs_only/phpdocs_like/all_multiline)的区别与适用场景、其底层的 Token 级修复原理、与其他 phpdoc 规则的执行优先级关系,以及如何在命令行和配置文件中启用它。
规则概览:它到底修复什么
按照官方文档(见 doc/rules/phpdoc/align_multiline_comment.rst)的表述,该规则的核心职责是:
Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one.
即:多行 DocComment 的每一行都必须有星号,且必须与第一行对齐。这一要求源自 PSR-5(已被放弃但影响深远的 PHPDoc 规范草案)对 DocComment 结构的规定。
实际开发中,代码格式化工具、IDE 重构、手工复制粘贴常常产生两类"脏"注释:
- 某行缺少前导星号(如
with a line not prefixed with asterisk); - 星号存在但缩进错乱(星号不在同一垂直列上)。
该规则会把它们统一整理成规范形态。源码实现位于 src/Fixer/Phpdoc/AlignMultilineCommentFixer.php,测试位于 tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php,后者定义的每一个用例都属于官方向后兼容承诺的一部分。
可配置项 comment_type:三种修复范围
该规则是CONFIGURABLE(可配置)的,唯一选项为comment_type,官方文档给出的定义如下:
| 取值 | 含义 | 处理对象 |
|---|---|---|
phpdocs_only(默认) | 只修复 PHPDoc 注释 | 仅T_DOC_COMMENT |
phpdocs_like | 修复所有"每一行都以星号开头"的多行注释 | T_DOC_COMMENT+ 符合形态的T_COMMENT |
all_multiline | 修复所有多行注释 | T_DOC_COMMENT+ 所有T_COMMENT |
- 允许的值:
'all_multiline'、'phpdocs_like'、'phpdocs_only' - 默认值:
'phpdocs_only'
从源码看,该配置直接决定了 fixer 的候选 Token 范围。configurePostNormalisation()方法(见 src/Fixer/Phpdoc/AlignMultilineCommentFixer.php)总是把T_DOC_COMMENT纳入tokenKinds,只有comment_type不等于phpdocs_only时才追加T_COMMENT;而isCandidate()则依据这两个 Token 类型判断文件是否值得处理(同文件 L109-L112)。选项的合法性校验通过FixerOptionBuilder::setAllowedValues()完成(L177-L185),传入非法值时抛出InvalidFixerConfigurationException——测试testInvalidConfiguration已验证这一行为(见 tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php)。
三种配置的差异本质
三种模式在处理普通多行注释(T_COMMENT)时行为不同,这正是phpdocs_like与all_multiline的关键区别。看源码applyFix()中的守卫条件(L146-L148):
- 对于
T_COMMENT,当comment_type不是all_multiline时,如果注释内容中存在"空行、或以非星号字符开头的行",则该注释整体被跳过、不修复; - 而当
comment_type为all_multiline时,这个守卫被绕过,所有多行注释都被纳入修复。
也就是说:phpdocs_like只收拾"看起来像 DocBlock 的块注释"(每一行都规规矩矩以星号开头,只是对齐不齐),而all_multiline连"内部混有裸文本行"的块注释也会强行改造。
三个官方示例详解
文档给出了三个 diff 形式的示例,下面逐一说明。
示例 #1:默认配置phpdocs_only
输入:
<?php /** * This is a DOC Comment with a line not prefixed with asterisk */输出:
<?php /** * This is a DOC Comment * with a line not prefixed with asterisk * */这是最典型的场景:/**是T_DOC_COMMENT,被默认配置命中。所有后续行统一补上星号、并以首行缩进对齐。注意空行也被补成了*(单独一个星号的行)。
示例 #2:['comment_type' => 'phpdocs_like']
输入:
<?php /* * This is a doc-like multiline comment */输出:
<?php /* * This is a doc-like multiline comment */这里注释以/*开头,属于普通注释(T_COMMENT),但内部每一行都以星号开头,形态上"像 PHPDoc",因此被phpdocs_like选中并对齐。测试用例也验证了该行为:tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php中有一组用例专门确认phpdocs_like会把/*\n * Doc-like Multiline comment\n *\n*\n */中对不齐的星号统一到同一列(见测试文件 L76-L90)。
示例 #3:['comment_type' => 'all_multiline']
输入:
<?php /* * This is a doc-like multiline comment with a line not prefixed with asterisk */输出:
<?php /* * This is a doc-like multiline comment * with a line not prefixed with asterisk * */与前一个示例对比可见:多了一行"以裸文本开头"的内容,在phpdocs_like下整块注释会被跳过,但在all_multiline下会连裸文本行一起补上星号并对齐。测试文件中的另一组用例(L117-L133)同样验证了all_multiline对混有裸文本行的块注释会进行全量修复。
源码级原理:修复是如何逐行完成的
深入 src/Fixer/Phpdoc/AlignMultilineCommentFixer.php 的applyFix()方法,可以看到完整修复流程:
- 读取行结束符:通过
whitespacesConfig->getLineEnding()获取项目配置的换行符(\n或\r\n)。测试中专门用new WhitespacesFixerConfig("\t", "\r\n")验证了 CRLF 环境下输出保持\r\n(见测试 L66-L74)。 - 定位注释 Token:遍历 Token 流,只处理
tokenKinds命中的注释 Token;通过向前查看 Token 收集注释前的空白与缩进。若注释紧跟在T_OPEN_TAG后,还会用Preg::replace('/\S/', '', ...)把开标签行内非空白字符清掉来叠加计算缩进,保证文件开头无换行的注释也能正确对齐。 - 计算基准缩进:用正则
/\R(\h*)$/从注释前的空白中取出最后一行的水平缩进,作为对齐基准;若取不到(注释不在新行起始处),则跳过该注释。 - 逐行重组:按换行符拆分注释内容,对除第一行外的每一行:
- 先
ltrim去掉行首空格; T_COMMENT下若该行不以*开头则跳过(与上文phpdocs_like守卫配合);- 空行补成
*,非星号开头的行补成*前缀; - 最终统一写成
缩进 + ' ' + 行内容。
- 先
- 回写 Token:用
implode($lineEnding, $lines)拼接后构造新 Token 替换原 Token。
值得注意的是,修复基准始终取"注释 Token 前一行"的缩进,而不是某个固定列,因此无论注释位于顶层、类内还是数组元素之间,都能跟随上下文缩进对齐。
与其他规则的执行顺序(Priority)
align_multiline_comment的优先级为27(见 getPriority()),其文档注释明确了执行顺序约束:
- 必须运行在
ArrayIndentationFixer之后:因为数组缩进修复后,注释的基准缩进才是最终值。仓库中的集成测试tests/Fixtures/Integration/priority/array_indentation,align_multiline_comment.test直接验证了这一顺序——输入中注释被过度缩进到与数组值平齐,array_indentation先把/*拉回正确缩进,随后align_multiline_comment把内部星号对齐到同一列。 - 必须运行在大量 phpdoc 类 fixer之前(包括
PhpdocAlignFixer、PhpdocTrimFixer、PhpdocSummaryFixer、PhpdocSeparationFixer、NoEmptyPhpdocFixer、PhpdocToCommentFixer等 30 余个):因为这些规则大多假设注释已经是"每行带星号"的规范形态。例如集成测试tests/Fixtures/Integration/priority/align_multiline_comment,phpdoc_trim_consecutive_blank_line_separation.test表明:先由align_multiline_comment把空行统一成*,再由phpdoc_trim_consecutive_blank_line_separation裁剪连续空行,二者协作才能得到干净的 DocBlock。
规则集归属与启用方式
align_multiline_comment是以下两个官方规则集的组成部分(见文档 doc/rules/phpdoc/align_multiline_comment.rst 的 Rule sets 一节):
@PhpCsFixer(对应规则集文档 doc/ruleSets/PhpCsFixer.rst)@Symfony(对应 doc/ruleSets/Symfony.rst)
从源码看,@Symfony规则集定义中直接以'align_multiline_comment' => true启用(见 src/RuleSet/Sets/SymfonySet.php);而@PhpCsFixer通过'@Symfony' => true继承@Symfony并追加更多规则(见 src/RuleSet/Sets/PhpCsFixerSet.php),因此该规则对两个规则集都生效。
通过规则集启用
在项目根目录的.php-cs-fixer.php配置文件中:
<?php return (new PhpCsFixer\Config()) ->setRules([ '@Symfony' => true, // 或 '@PhpCsFixer' => true ]) ->setFinder( PhpCsFixer\Finder::create()->in(__DIR__) );单独启用并定制 comment_type
<?php return (new PhpCsFixer\Config()) ->setRules([ 'align_multiline_comment' => [ 'comment_type' => 'phpdocs_like', // 或 'phpdocs_only' / 'all_multiline' ], ]);命令行使用
也可以在 CLI 中临时指定规则运行:
# 只检查,不修改 php php-cs-fixer fix path/to/file.php --dry-run --rules='{"align_multiline_comment": {"comment_type": "phpdocs_like"}}' # 实际修复 php php-cs-fixer fix path/to/file.php --rules='{"align_multiline_comment": true}'边界行为:哪些注释不会被触碰
综合测试用例(见 tests/Fixer/Phpdoc/AlignMultilineCommentFixerTest.php),以下几类注释会原样保留:
- 单行注释:
/** inline doc comment */这类单行 DocBlock,以及#、//开头的单行注释,均不处理; - 不在新行起始处的注释:如
$a=1; /** ... */后跟的多行注释(无法稳定提取基准缩进); - 形态不匹配的块注释:默认配置下,
phpdocs_only只处理真正的 DocBlock;phpdocs_like会跳过内部存在空行或裸文本行的块注释; - 包含多字节字符的注释:测试中有专门命名为
uni code test的用例(L257-L273),确认对包含西里尔字母等 Unicode 内容的注释只对齐星号列、不破坏内容。
小结
align_multiline_comment是 PHP-CS-Fixer 在注释规范化层面的一道基础工序:它把"星号缺失、列不对齐"的多行注释统一成 PSR-5 风格的规范 DocBlock。通过comment_type一个选项即可精确控制作用范围——默认只动真正的 PHPDoc,phpdocs_like覆盖"形似 PHPDoc"的块注释,all_multiline则无差别处理所有多行注释。配合其 27 的优先级设计(数组缩进之后、其他 phpdoc 规则之前),它能与其他规则无缝衔接,因此被@Symfony、@PhpCsFixer两大主流规则集默认收录,是保证团队注释风格一致性的低成本高收益选择。
- 开发工具
- 代码质量
- 静态分析
- Lint
- 格式化
【免费下载链接】PHP-CS-Fixer
A tool to automatically fix PHP Coding Standards issues
相关推荐
PHP-CS-Fixer multiline_comment_opening_closing 规则详解:统一多行注释与 DocBlock 的开闭星号规范
PHP CS Fixer multiline_comment_opening_closing 规则详解:统一多行注释与 DocBlock 的开闭星号规范 本篇文
开发工具代码质量静态分析Lint格式化PHP-CS-Fixer 分号前多行空白规范:multiline_whitespace_before_semicolons 规则配置与实现解析
PHP CS Fixer 分号前多行空白规范:multiline_whitespace_before_semicolons 规则配置与实现解析 导读 multi
开发工具代码质量静态分析Lint格式化PHP-CS-Fixer 的 no_trailing_whitespace_in_comment 规则:清除注释与 PHPDoc 行尾空白
PHP CS Fixer 的 no_trailing_whitespace_in_comment 规则:清除注释与 PHPDoc 行尾空白 导读 no_trai
开发工具代码质量静态分析Lint格式化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考