PHP Linter 与规则定义小探

UioSun -
PHP Linter 与规则定义小探
本文旨在确认 PHPLint、PHP-CS-Fixer 和 PHP_CodeSniffer 的差异,根据当前公司的需求进行选择,并编写一个简单的自定义规则。Lint 工具浅析

PHPLint 是三者中我唯一用过的 Lint 工具,另外两个则是较为出名的 PHP 领域的自动化语法规范或静态错误定位工具。

每个工具都在安装、运行的基础上,测试三块:

展示错误,自动修复(如果有这个功能)某一行代码跳过特定检测切换规则集合。关闭一条规则。写一个自定义规则。

参考开源社区的活跃程度,本次主要的探索点也会放在后两者上。

PHP-CS-Fixer

环境说明,PHP 7.4 是它所需的最低版本。

提一嘴:请保证你的 PHP 最少处于 LTS 版本中,否则它将失去后续的安全补丁。

它支持多种安装方式:PHAR、Composer 等等。

通过 composer require friendsofphp/php-cs-fixer 安装,然后跑起来:vendor/bin/php-cs-fixer fix some_path

如果你装在全局,就不需要调用 vendor 目录的执行文件,不过考虑一下规范是否是全局的,否则写个 Shell 更合适。

展示错误,自动修复

以我写的 Laravel Demo 为例:vendor/bin/php-cs-fixer fix app/Http/,成功将我的 if (expression) once_line_code 给转化掉了,没啥毛病。

使用 vendor/bin/php-cs-fixer fix app/Http --dry-run --diff,这样不会修改文件,并能获取检测结果的具体问题和推荐修改。

某一行代码跳过特定检测

基于 Issue 4512,暂不支持。

切换规则集合

通过 /.php-cs-fixer.dist.php,你可以方便的定义自己的配置文件——里面涵盖了具体规则、规则集合、待检查的文件目录、剔除检查的目录等的变更。

简单的尝试:替换为 PSR12 并开启不安全修复模式,没问题。

关闭某条规则

这个工具采用的是最小规则默认,所以在配置文件中不包含,就可以放弃对应规则的检测。

CI

官方提供了对应的命令,使你高效的将其纳入 CI 构建流程。

编写自定义规则

尝试添加了一条 App/test_rule 规则。优点如下:

编写简单,在接口约束的前提下,基本上都是可读的 Function 编写;规则存放灵活,规则类可以直接放在任意项目路径下——写个包隔离出去也可以,如果你喜欢;参考性强,尽管缺乏足够的自定义规则编写指南,但你很容易就找到了所有的规则类,阅读、理解、编程,很好的循环。基本上遵循 \PhpCsFixer\Fixer\FixerInterface 接口即可,更多的自行参考文档。PHP_CodeSniffer

环境说明,PHP 5.4 是它所需的最低版本,但特定规则需要更高版本的 PHP 支持。

与 CS-Fixer 类似,也提供了多种安装方式,老样子:

composer require "squizlabs/php_codesniffer=*"

展示错误,自动修复

以我写的 Laravel Demo 为例:./vendor/bin/phpcs app/Http/

显示出了密密麻麻的错误数量提示:Line | Level | Message。很好,有 PHPLint 的味道了。

它的一个工具:phpcbf 可以让你自动修复发现的问题——如果能自动修复的话。

如果我们希望接入 CI,PHP CS 提供了对应的 Action,你可以将其融入到构建流程。

某一行代码跳过特定检测

CS 提供了跳过文件、跳过某行、暂时关闭,乃至下一行不检测某个规则。

简单测试了上述的,譬如通过 // phpcs:ignore,可以跳过某行检测,从文档里你可以找到更多、更详细的解释。

切换规则集合

通过 .phpcs.xml 或类似的文件(它竟然支持数个不同的名字……),我们可以定义配置:

<rule ref="/path/to/standards/Generic/Sniffs/Commenting/TodoSniff.php"/>

这样就添加了对应的 ToDo Sniff 规则。

关闭某条规则

与 CS Fixer 一致,只要不包含对应规则即可。我们感受到它默认支持很多规则,是因为它的默认配置比较全面。

命名相较 CS Fixer 更简单,但规则列表比较难找。

CI

PHP CS 官方支持的是 Github CI Action,对于分发和 diff 需求,并没有合适的支持。

尽管如此,你可以通过 diffFilter 为其提供基于 commit 或 PR 范围的合理提示。

尝试了一下,调整 Shell 和钩子相比较 PHP CS Fixer 略微耗时。

编写自定义规则

CS 将规则称呼为嗅探器(Sniff),支持 PSR2、PSR12 等通用规则。感觉规则比 Fixer 提供的少一些,不过没关系,我们来尝试添加了一条 test_rule 规则。

首先指出,CS 有完整地 Step-To-Step 教程指导你如何写自己的规则,如果你希望使用 CS 在自己的技术栈中,推荐直接阅读它(官方的 Wiki 指南),而不是我这样的博客文章。

开工。

首先,让我们像 Fixer 一样,在项目中直接创建自己的规则目录和文件,保持灵活的同时,后期依旧可以将其抽离为 Composer Package。

我们管容纳自定义规则集合、定义文件等的目录叫 MyStandard,进入其中并创建 ruleset.xml——它可以定义规则具体的条件。

格式大略为:

<?xml version="1.0"?>
<ruleset name="MyStandard">
  <description>A custom coding standard.</description>
</ruleset>
所以,这个规则就被称为 MyStandard 规则集,里面将包含一个或若干的实际嗅探器来执行检查。

接着创建目录 MyStandard/Sniffs,为了不让你困惑,我直接用嵌套结构表示它的实际位置。这里将容纳嗅探器文件。

然后我们对评论进行嗅探,继续创建目录 MyStandard/Sniffs/Commenting,在其中创建 DisallowHashCommentsSniff.php 嗅探器(文件)。

Sniffs 下的目录其实不重要,只是为了方便我们将更多嗅探器区分开,你如果喜欢,也可以将百十来个规则丢在一起,实现软件工程师们深恶痛绝的“大杂烩”(:D)。

与 Fixer 一样,它也规定了一个接口——Only Once,PHP_CodeSniffer\Sniffs\Sniff,继承并实现关键方法就好。

supportedTokenizers 属性定义:嗅探的文件类型,PHP、JS、Rust、etc.register 方法定义:嗅探的代码类型,单行注释、多行注释、单行代码、代码块、etc.

process 方法定义:实际的错误检查、处理。

系统提供了 addError / addWarning 作为报错信息的添加方法。
    public function process(File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        if ($tokens[$stackPtr]['content']{0} === '#') {
            $error = 'Hash comments are prohibited; found %s';
            $data  = array(trim($tokens[$stackPtr]['content']));
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }
    }

最终,我们采用 phpcs --standard=/path/to/MyStandard has_error_code.php 尝试检测一个 has_error_code.php 文件,里面包含了一些错误。

/path/to/MyStandard 定义了我们规则集合的位置,以帮助 CS 寻找包外的规则集。

试试看吧!

最后,嗅探的文件类型不支持 Rust,那是开玩笑的——尽管你可以让它支持——这很诡异。
无论怎样,更喜欢哪个工具,都祝你玩的愉快!
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

php介绍

PHP即“超文本预处理器”,是一种通用开源脚本语言。PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言。PHP独特的语法混合了C、Java、Perl以及 PHP 自创的语法。利于学习,使用广泛,主要适用于Web开发领域。

Tags 标签

phplinter规范化ci

扩展阅读

加个好友,技术交流

1628738909466805.jpg