PHP中的代码格式化工具:使用PHP-CS-Fixer与PHP Code Sniffer统一代码风格

PHP代码格式化工具:使用PHP-CS-Fixer与PHP Code Sniffer统一代码风格

大家好!今天我们来聊聊PHP代码格式化,以及如何利用PHP-CS-Fixer和PHP Code Sniffer (PHPCS) 这两个强大的工具,来统一团队的代码风格,提升代码质量和可维护性。

为什么代码格式化如此重要?

在软件开发中,尤其是在团队协作的项目中,代码风格的一致性至关重要。想象一下,一个项目中,不同的开发者使用不同的缩进方式、命名规范、注释风格等等,代码阅读和维护将会变得异常困难。

代码格式化可以带来以下好处:

  • 提高代码可读性: 一致的风格让代码更容易理解,降低阅读成本。
  • 减少代码审查时间: 审查者可以专注于代码逻辑,而不是纠结于格式问题。
  • 降低出错概率: 统一的风格可以减少因代码风格差异而引入的错误。
  • 提升团队协作效率: 开发者更容易理解和修改彼此的代码,协作更加顺畅。
  • 便于代码维护: 风格一致的代码更容易维护和重构。

简单来说,代码格式化是代码质量保证的第一步,也是团队协作的基础。

PHP-CS-Fixer 和 PHP Code Sniffer: 两个利器

PHP-CS-Fixer 和 PHP Code Sniffer 是两个用于 PHP 代码格式化的强大工具,但它们的功能侧重点有所不同。

  • PHP Code Sniffer (PHPCS): 是一个代码风格检测工具,它会扫描你的代码,并根据预定义的规则集(standards)来检查代码是否符合规范。PHPCS 发现违反规则的地方,会给出警告或错误信息,但 不会 自动修复代码。

  • PHP-CS-Fixer: 是一个代码风格修复工具。它可以自动修正代码中违反预定义规则的地方,使其符合规范。PHP-CS-Fixer 依赖于 PHPCS 定义的规则,但其目标是 自动修复 代码,而不仅仅是检测问题。

可以将 PHPCS 看作是一个代码风格的“检查员”,而 PHP-CS-Fixer 则是“修理工”。通常,我们会先使用 PHPCS 检查代码,然后使用 PHP-CS-Fixer 自动修复代码中违反规则的地方。

安装 PHP-CS-Fixer 和 PHP Code Sniffer

推荐使用 Composer 来安装这两个工具。

  1. 全局安装 (推荐):

    composer global require friendsofphp/php-cs-fixer
    composer global require squizlabs/php_codesniffer

    全局安装后,你可以在任何目录下直接使用 php-cs-fixerphpcs 命令。

  2. 项目内安装:

    在你的项目目录下运行:

    composer require --dev friendsofphp/php-cs-fixer
    composer require --dev squizlabs/php_codesniffer

    项目内安装后,你需要使用 vendor/bin/php-cs-fixervendor/bin/phpcs 来运行命令。

安装完成后,可以通过运行以下命令来验证安装是否成功:

php-cs-fixer --version
phpcs --version

如果能正确显示版本信息,则说明安装成功。

配置 PHP Code Sniffer (PHPCS)

PHPCS 需要一个规则集(standard)来定义代码风格规范。PHPCS 提供了几个内置的标准,例如:

  • PSR1: 遵循 PSR-1 规范。
  • PSR2: 遵循 PSR-2 规范。
  • PSR12: 遵循 PSR-12 规范。 (推荐)
  • Squiz: Squiz 团队的代码风格规范。
  • PEAR: PEAR 项目的代码风格规范。

你可以使用内置的标准,也可以自定义规则集。

  1. 使用内置标准:

    假设我们想使用 PSR-12 标准来检查代码,可以使用以下命令:

    phpcs --standard=PSR12 your_file.php
    phpcs --standard=PSR12 your_directory/

    your_file.phpyour_directory/ 是你要检查的文件或目录。

  2. 自定义规则集 (ruleset.xml):

    如果内置的标准不能满足你的需求,你可以创建一个 ruleset.xml 文件来定义自己的规则集。

    例如,创建一个名为 ruleset.xml 的文件,内容如下:

    <?xml version="1.0"?>
    <ruleset name="MyProject">
        <description>My Project Coding Standard</description>
    
        <!-- Inherit the PSR12 standard -->
        <rule ref="PSR12"/>
    
        <!-- Add custom rules or overrides -->
        <rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
        <rule ref="Squiz.Commenting.FunctionComment.MissingParamComment">
            <exclude name="Squiz.Commenting.FunctionComment.MissingParamComment"/>
        </rule>
        <rule ref="Generic.Formatting.MultipleStatementAlignment">
            <properties>
                <property name="error" value="true"/>
                <property name="maxStmts" value="1"/>
            </properties>
        </rule>
    </ruleset>
    • ruleset 标签定义了规则集的名称和描述。
    • rule ref 标签引用一个规则。可以使用内置的规则,也可以自定义规则。
    • exclude 标签排除某个规则。
    • properties 标签设置规则的属性。

    在这个例子中,我们继承了 PSR-12 标准,并添加了一些自定义规则:

    • Generic.Arrays.DisallowLongArraySyntax: 禁止使用长数组语法 (array()),推荐使用短数组语法 ([])。
    • Squiz.Commenting.FunctionComment.MissingParamComment: 排除了缺少参数注释的规则。 (这个例子是刻意展示排除规则)
    • Generic.Formatting.MultipleStatementAlignment: 强制要求一行只能有一个语句。

    使用自定义规则集:

    phpcs --standard=ruleset.xml your_file.php
    phpcs --standard=ruleset.xml your_directory/

    或者,你可以将规则集注册为标准名称:

    phpcs --config-set installed_paths /path/to/your/ruleset.xml
    phpcs --standard=MyProject your_file.php

    替换 /path/to/your/ruleset.xml 为你的 ruleset.xml 文件的实际路径。 MyProject 是你在 ruleset.xml 中定义的 name 属性值。

配置 PHP-CS-Fixer

PHP-CS-Fixer 的配置主要通过 .php-cs-fixer.php 文件来实现。这个文件位于项目的根目录下。

以下是一个 .php-cs-fixer.php 文件的示例:

<?php

use PhpCsFixerConfig;
use PhpCsFixerFinder;

$finder = Finder::create()
    ->in(__DIR__)
    ->exclude('var')
    ->exclude('vendor');

return (new Config())
    ->setRules([
        '@PSR12' => true,
        'array_syntax' => ['syntax' => 'short'],
        'ordered_imports' => ['sort_algorithm' => 'alpha'],
        'no_unused_imports' => true,
        'not_operator_with_successor_space' => true,
        'trailing_comma_in_multiline' => ['elements' => ['arrays']],
        'phpdoc_scalar' => true,
        'unary_operator_spaces' => true,
        'binary_operator_spaces' => true,
        'blank_line_before_statement' => [
            'statements' => ['return', 'throw', 'try']
        ],
        'single_quote' => true,
        'concat_space' => ['spacing' => 'one'],
        'class_attributes_separation' => ['elements' => ['method' => 'one', 'property' => 'one']],
    ])
    ->setFinder($finder)
    ->setRiskyAllowed(true)
    ->setUsingCache(true);
  • Finder: 用于定义要修复的文件和目录。

    • in(__DIR__) 表示在当前目录及其子目录中查找文件。
    • exclude('var')exclude('vendor') 表示排除 varvendor 目录。
  • Config: 用于配置修复规则。

    • setRules() 方法用于设置规则。
      • '@PSR12' => true 表示启用 PSR-12 规则集。
      • 'array_syntax' => ['syntax' => 'short'] 表示使用短数组语法。
      • 'ordered_imports' => ['sort_algorithm' => 'alpha'] 表示按照字母顺序对 imports 进行排序。
      • 'no_unused_imports' => true 表示移除未使用的 imports。
      • 等等…
    • setFinder() 方法用于设置 Finder 对象。
    • setRiskyAllowed(true) 表示允许使用 "risky" 规则。"Risky" 规则可能会修改代码的行为,例如修改函数的参数顺序。
    • setUsingCache(true) 表示启用缓存,可以提高修复速度。

常用的 PHP-CS-Fixer 规则:

以下是一些常用的 PHP-CS-Fixer 规则,以及它们的简要说明:

规则名称 描述
@PSR12 遵循 PSR-12 规范。
array_syntax 强制使用短数组语法 ([]) 或长数组语法 (array())。
ordered_imports 对 imports 进行排序。
no_unused_imports 移除未使用的 imports。
trailing_comma_in_multiline 在多行数组、函数参数列表等中添加尾随逗号。
phpdoc_scalar 强制 phpdoc 中标量类型使用小写。
unary_operator_spaces 强制一元运算符周围的空格。
binary_operator_spaces 强制二元运算符周围的空格。
blank_line_before_statement 在指定的语句(例如 return, throw)之前添加空行。
single_quote 强制使用单引号字符串。
concat_space 强制字符串连接符 (.) 周围的空格。
class_attributes_separation 强制类属性之间的分隔方式。
phpdoc_separation 强制 phpdoc 中不同的块之间用空行分隔。
method_argument_space 强制方法参数列表中的空格。
no_whitespace_in_blank_line 移除空行中的空格。
no_extra_blank_lines 移除多余的空行。
whitespace_after_comma_in_array 强制数组中逗号后的空格。
function_typehint_space 强制函数类型提示后的空格。
return_type_declaration 强制返回类型声明的格式。
fully_qualified_strict_types 总是使用完全限定的类型名,即使在同一个命名空间中。
global_namespace_import 总是导入全局命名空间中的类、函数和常量。
no_superfluous_phpdoc_tags 移除多余的 phpdoc 标签。
no_empty_phpdoc 移除空的 phpdoc。
phpdoc_summary 强制 phpdoc summary 以句号结尾。
phpdoc_to_comment 将简单的 phpdoc 转换为注释。
phpdoc_var_without_name 移除 phpdoc var 标签中的变量名。
phpdoc_align 对齐 phpdoc 中的标签。
single_line_comment_style 强制单行注释的风格 (例如 //#)。
include 强制使用 include, include_once, require, require_once 的格式。
increment_style 强制使用前置递增/递减运算符 (++$i, --$i) 或后置递增/递减运算符 ($i++, $i--)。
new_with_braces 总是使用 new 关键字创建对象时带括号。
no_trailing_whitespace 移除行尾的空格。
no_whitespace_before_comma_in_array 移除数组中逗号前的空格。
object_operator_without_whitespace 移除对象操作符 (->) 周围的空格。
standardize_notations != 转换为 <>
ternary_operator_spaces 强制三元运算符周围的空格。
ternary_to_null_coalescing 将简单的三元运算符转换为 null 合并运算符 (??)。
elseif 强制使用 elseif 而不是 else if

注意: 规则的选择应该基于你的项目需求和团队的偏好。 建议从一个基础的规则集 (例如 @PSR12) 开始,然后根据需要添加或修改规则。

运行 PHP-CS-Fixer

配置好 .php-cs-fixer.php 文件后,就可以运行 PHP-CS-Fixer 来修复代码了。

php-cs-fixer fix

这个命令会修复当前目录下所有符合 Finder 规则的文件。

  • 指定文件或目录:

    php-cs-fixer fix your_file.php
    php-cs-fixer fix your_directory/
  • 使用不同的配置文件:

    php-cs-fixer fix --config=/path/to/.php-cs-fixer.php
  • Dry Run (不实际修改文件):

    使用 --dry-run 选项可以模拟修复过程,但不会实际修改文件。这可以让你在修改代码之前预览修复结果。

    php-cs-fixer fix --dry-run
  • Verbose 模式:

    使用 --verbose 选项可以显示更详细的输出信息。

    php-cs-fixer fix --verbose
  • Diff 模式:

    使用 --diff 选项可以生成一个 diff 文件,显示修复前后的差异。

    php-cs-fixer fix --diff

    可以将 diff 文件保存到文件中:

    php-cs-fixer fix --diff > changes.diff

将 PHP-CS-Fixer 和 PHPCS 集成到开发流程中

为了确保代码风格的一致性,建议将 PHP-CS-Fixer 和 PHPCS 集成到你的开发流程中。

  1. Git Hooks:

    可以使用 Git hooks 在提交代码之前自动运行 PHP-CS-Fixer 和 PHPCS。例如,在 .git/hooks/pre-commit 文件中添加以下内容:

    #!/bin/sh
    
    echo "Running PHP Code Sniffer..."
    vendor/bin/phpcs --standard=PSR12 src/ tests/
    
    if [ $? -ne 0 ]; then
      echo "PHP Code Sniffer found errors. Please fix them before committing."
      exit 1
    fi
    
    echo "Running PHP-CS-Fixer..."
    vendor/bin/php-cs-fixer fix
    
    if [ $? -ne 0 ]; then
      echo "PHP-CS-Fixer found errors. Please fix them before committing."
      exit 1
    fi
    
    echo "Code style check passed."
    exit 0

    确保 .git/hooks/pre-commit 文件具有可执行权限 (chmod +x .git/hooks/pre-commit)。

    注意: 如果使用全局安装的 PHP-CS-Fixer 和 PHPCS,需要将 vendor/bin/phpcsvendor/bin/php-cs-fixer 替换为 phpcsphp-cs-fixer

  2. CI/CD:

    可以将 PHP-CS-Fixer 和 PHPCS 集成到你的 CI/CD 流程中,例如使用 Jenkins, GitLab CI, GitHub Actions 等。

    以下是一个 GitHub Actions 的示例:

    name: Code Style
    
    on:
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    
    jobs:
      php-cs-fixer:
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v3
          - name: Setup PHP
            uses: shivammathur/setup-php@v2
            with:
              php-version: '8.1'
              extensions: dom, curl, libxml, mbstring, intl, json, mysqlnd, zip, gd
    
          - name: Install dependencies
            run: composer install --no-interaction --no-progress --prefer-dist
    
          - name: Run PHP-CS-Fixer
            run: vendor/bin/php-cs-fixer fix --dry-run --diff

    这个 workflow 会在每次 push 或 pull request 到 main 分支时运行 PHP-CS-Fixer,并检查代码风格是否符合规范。如果发现错误,workflow 会失败。

  3. IDE 集成:

    许多 IDE (例如 PHPStorm, VS Code) 提供了对 PHP-CS-Fixer 和 PHPCS 的集成。你可以配置 IDE 在保存文件时自动运行 PHP-CS-Fixer,或者在代码编辑器中显示 PHPCS 的警告和错误信息。

处理大型项目的代码风格迁移

对于已经存在的大型项目,进行代码风格迁移可能会比较困难。建议采取以下步骤:

  1. 逐步迁移: 不要试图一次性修复所有代码。可以先从一部分代码开始,逐步扩大范围。
  2. 制定明确的规则: 在开始迁移之前,制定明确的代码风格规范,并将其写入文档。
  3. 使用工具: 充分利用 PHP-CS-Fixer 和 PHPCS 的功能,尽可能自动化修复过程。
  4. 团队协作: 与团队成员沟通,确保每个人都理解并接受新的代码风格规范。
  5. 代码审查: 在迁移过程中,进行代码审查,确保代码风格的一致性。

总结

PHP-CS-Fixer 和 PHP Code Sniffer 是 PHP 代码格式化的两个利器。通过合理配置和使用这两个工具,可以有效地统一团队的代码风格,提高代码质量和可维护性,并最终提升开发效率。 记住,代码风格不仅仅是美观,更是代码质量的体现。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注