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

好的,没问题。

PHP代码格式化:PHP-CS-Fixer与PHP Code Sniffer的实践应用

各位同学,大家好。今天我们要聊聊PHP代码格式化的问题,以及如何利用PHP-CS-Fixer和PHP Code Sniffer这两大利器,统一团队的代码风格,提升代码质量。

首先,我们来明确一下为什么代码格式化如此重要。

为什么需要代码格式化?

  1. 提高可读性: 一致的代码风格,如缩进、空格、换行等,能显著提高代码的可读性,方便团队成员理解和维护。
  2. 减少代码审查负担: 统一的风格减少了代码审查过程中关于格式问题的争论,使审查人员能更专注于逻辑错误和代码质量。
  3. 降低维护成本: 长期来看,良好的代码风格可以降低代码的维护成本,减少潜在的错误。
  4. 团队协作: 在团队开发中,统一的代码风格是高效协作的基础。

PHP-CS-Fixer 与 PHP Code Sniffer 的区别

特性 PHP-CS-Fixer PHP Code Sniffer
主要功能 自动修复代码风格问题 检测代码风格问题,但不自动修复
工作方式 修改代码 报告问题
适用场景 自动格式化代码,批量处理现有代码 代码审查,持续集成,静态分析
优点 自动修复,节省时间 可定制性强,规则灵活
缺点 配置较为复杂,可能过度修复 需要手动修复问题,效率较低

简单来说,PHP-CS-Fixer 是一个自动修复工具,它可以直接修改你的代码,使其符合指定的风格规范。而 PHP Code Sniffer 则是一个检测工具,它会告诉你代码中存在哪些风格问题,但需要你手动去修改。

1. PHP Code Sniffer (phpcs) 的安装与配置

首先,我们需要安装 PHP Code Sniffer。推荐使用 Composer 进行安装:

composer require --dev squizlabs/php_codesniffer

安装完成后,你可以在 vendor/bin 目录下找到 phpcs 可执行文件。为了方便使用,可以将它添加到系统的 PATH 环境变量中。

1.1. 使用 phpcs 检测代码

假设我们有一个名为 example.php 的文件,内容如下:

<?php

namespace MyProject;

class Example {
  public function myFunction( $arg1,$arg2 ) {
    if($arg1 > 10) {
      return true;
    }
    return false;
  }
}

我们可以使用 phpcs 命令来检测这个文件:

./vendor/bin/phpcs example.php

默认情况下,phpcs 使用 PEAR 标准来检测代码风格。你可能会看到类似以下的输出:

FILE: /path/to/example.php
----------------------------------------------------------------------
FOUND 11 ERRORS AND 3 WARNINGS AFFECTING 9 LINES
----------------------------------------------------------------------
  2 | ERROR | [x] Expected 1 blank line after namespace statement; 0 found
  6 | ERROR | [x] Expected 1 space after opening parenthesis
  6 | ERROR | [x] Expected 1 space before closing parenthesis
  6 | ERROR | [x] Space found after comma
  6 | ERROR | [x] Space found before comma
  6 | ERROR | [x] Expected 1 space after comma; 0 found
  7 | ERROR | [x] Space found before opening brace
  7 | WARNING | [x] Opening brace should be on the line after the keyword
  9 | ERROR | [x] Space found before keyword
 10 | ERROR | [x] Space found before keyword
 11 | ERROR | [x] Space found before closing brace
 12 | WARNING | [x] Missing newline at end of file
----------------------------------------------------------------------
PHPCBF CAN FIX THE 11 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

这个输出告诉我们,example.php 文件中存在 11 个错误和 3 个警告,并且 PHPCBF (PHP Code Beautifier and Fixer,与 phpcs 配套的自动修复工具,将在后面介绍) 可以自动修复 11 个错误。

1.2. 选择代码风格标准

除了 PEAR 标准,phpcs 还支持其他一些常用的代码风格标准,例如:

  • PSR1: PSR-1 基本编码规范
  • PSR2: PSR-2 编码风格指南
  • PSR12: PSR-12 扩展编码风格指南
  • Squiz: Squiz 编码标准 (PHP_CodeSniffer 的默认标准)
  • Zend: Zend 编码标准

你可以使用 --standard 参数来指定要使用的标准:

./vendor/bin/phpcs --standard=PSR12 example.php

不同的标准会产生不同的结果。通常,建议使用 PSR-12 标准,因为它是一个被广泛接受的现代 PHP 代码风格规范。

1.3. 创建自定义规则集 (ruleset.xml)

如果你想使用自定义的代码风格规则,可以创建一个 ruleset.xml 文件。这个文件定义了要使用的标准、要排除的文件或目录、以及其他一些配置选项。

下面是一个简单的 ruleset.xml 示例:

<?xml version="1.0"?>
<ruleset name="MyProject">
    <description>My Project Coding Standard</description>

    <rule ref="PSR12"/>

    <exclude-pattern>*/tests/*</exclude-pattern>
    <exclude-pattern>*/vendor/*</exclude-pattern>

    <arg name="colors"/>
</ruleset>

这个 ruleset.xml 文件指定了使用 PSR-12 标准,并排除了 testsvendor 目录。<arg name="colors"/> 启用彩色输出。

要使用自定义规则集,可以使用 --standard 参数指定 ruleset.xml 文件的路径:

./vendor/bin/phpcs --standard=ruleset.xml example.php

2. PHP Code Beautifier and Fixer (phpcbf) 的使用

PHP Code Beautifier and Fixer (phpcbf) 是 phpcs 的配套工具,它可以自动修复一些简单的代码风格问题。

2.1. 使用 phpcbf 自动修复代码

使用 phpcbf 的方法与 phpcs 类似:

./vendor/bin/phpcbf example.php

phpcbf 会尝试修复 example.php 文件中的代码风格问题。

同样,你可以使用 --standard 参数来指定要使用的标准:

./vendor/bin/phpcbf --standard=PSR12 example.php

或者使用自定义规则集:

./vendor/bin/phpcbf --standard=ruleset.xml example.php

2.2. 注意事项

  • phpcbf 只能自动修复一些简单的代码风格问题。对于更复杂的问题,仍然需要手动修改。
  • 在运行 phpcbf 之前,最好先备份你的代码,以防止意外的修改。
  • phpcbf 的修复能力取决于所使用的标准。不同的标准支持的自动修复规则不同。

3. PHP-CS-Fixer 的安装与配置

PHP-CS-Fixer 是一个功能强大的 PHP 代码风格修复工具,它可以自动修复大量代码风格问题,比 phpcbf 更强大。

同样,推荐使用 Composer 进行安装:

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

安装完成后,你可以在 vendor/bin 目录下找到 php-cs-fixer 可执行文件。为了方便使用,可以将它添加到系统的 PATH 环境变量中。

3.1. 使用 PHP-CS-Fixer 修复代码

PHP-CS-Fixer 的基本使用方法如下:

./vendor/bin/php-cs-fixer fix example.php

这个命令会尝试修复 example.php 文件中的代码风格问题,并直接修改文件。

3.2. 配置 PHP-CS-Fixer (.php-cs-fixer.dist.php)

PHP-CS-Fixer 的强大之处在于它的可配置性。你可以通过创建一个 .php-cs-fixer.dist.php 文件来定义要使用的代码风格规则。

下面是一个简单的 .php-cs-fixer.dist.php 示例:

<?php

use PhpCsFixerConfig;
use PhpCsFixerFinder;

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

return (new Config())
    ->setRules([
        '@PSR12' => true,
        'array_syntax' => ['syntax' => 'short'],
        'ordered_imports' => ['sort_algorithm' => 'alpha'],
        'no_unused_imports' => true,
    ])
    ->setFinder($finder)
    ->setRiskyAllowed(true)
    ->setUsingCache(true);

这个配置文件指定了以下规则:

  • @PSR12: 使用 PSR-12 标准。
  • array_syntax: 使用短数组语法 ([] 代替 array())。
  • ordered_imports: 对 use 语句进行排序。
  • no_unused_imports: 移除未使用的 use 语句。
  • setFinder: 指定要处理的文件和目录。
  • setRiskyAllowed(true): 允许使用一些可能存在风险的规则。
  • setUsingCache(true): 启用缓存,提高修复速度。

3.3. PHP-CS-Fixer 常用规则

PHP-CS-Fixer 提供了大量的代码风格规则,你可以根据自己的需要选择合适的规则。以下是一些常用的规则:

  • align_multiline_comment: 对齐多行注释。
  • array_indentation: 数组元素缩进。
  • array_syntax: 数组语法 (short 或 long)。
  • binary_operator_spaces: 二元运算符周围的空格。
  • blank_line_after_namespace: 在命名空间声明后添加空行。
  • braces: 控制结构的花括号风格。
  • cast_spaces: 类型转换操作符周围的空格。
  • class_attributes_separation: 类属性之间的分隔符。
  • class_definition: 类定义的风格。
  • concat_space: 字符串连接符周围的空格。
  • declare_equal_normalize: declare 语句中的等号周围的空格。
  • elseif: 使用 elseif 代替 else if
  • encoding: 强制使用 UTF-8 编码。
  • full_opening_tag: 使用完整的 PHP 开始标签 (<?php)。
  • function_declaration: 函数声明的风格。
  • function_typehint_space: 函数类型提示周围的空格。
  • heredoc_to_nowdoc: 将 heredoc 转换为 nowdoc (如果可能)。
  • include: 使用 includerequire 时,强制使用括号。
  • increment_style: 自增/自减运算符的风格。
  • indentation_type: 缩进类型 (space 或 tab)。
  • line_ending: 行尾符 (LF 或 CRLF)。
  • lowercase_constants: 常量名强制小写。
  • lowercase_keywords: 关键字强制小写。
  • method_argument_space: 方法参数周围的空格。
  • method_chaining_indentation: 方法链式调用缩进。
  • multiline_whitespace_before_semicolons: 多行语句中分号前的空格。
  • no_blank_lines_after_phpdoc: 移除 phpdoc 后的空行。
  • no_empty_phpdoc: 移除空的 phpdoc。
  • no_extra_blank_lines: 移除多余的空行。
  • no_leading_import_slash: 移除 use 语句中的前导斜杠。
  • no_leading_namespace_whitespace: 移除命名空间声明前的空白。
  • no_mixed_echo_print: 避免同时使用 echoprint
  • no_multiline_whitespace_around_double_arrow: 移除双箭头符号周围的多余空白。
  • no_short_bool_cast: 使用 (bool) 代替 (boolean)
  • no_singleline_whitespace_before_semicolons: 移除单行语句中分号前的空白。
  • no_spaces_after_function_name: 移除函数名后的空格。
  • no_spaces_inside_parenthesis: 移除括号内的空格。
  • no_trailing_whitespace: 移除行尾的空白。
  • no_unused_imports: 移除未使用的 use 语句。
  • normalize_index_brace: 规范化数组索引的括号。
  • object_operator_without_whitespace: 对象操作符周围不允许有空白。
  • ordered_imports: 对 use 语句进行排序。
  • phpdoc_align: 对齐 phpdoc 中的注释。
  • phpdoc_annotation_without_dot: phpdoc 注释中不允许有点号。
  • phpdoc_indent: phpdoc 缩进。
  • phpdoc_inline_tag_normalizer: 规范化 phpdoc 内联标签。
  • phpdoc_no_access: 移除 @access 标签。
  • phpdoc_no_package: 移除 @package 标签。
  • phpdoc_no_useless_inheritdoc: 移除无用的 @inheritdoc 标签。
  • phpdoc_scalar: phpdoc 中标量类型强制使用小写。
  • phpdoc_separation: phpdoc 标签之间使用空行分隔。
  • phpdoc_single_line_var_spacing: 单行 phpdoc 中变量周围的空格。
  • phpdoc_summary: phpdoc 摘要必须以句号结尾。
  • phpdoc_to_comment: 将 phpdoc 转换为普通注释 (如果可能)。
  • phpdoc_trim: 移除 phpdoc 前后多余的空白。
  • phpdoc_types: phpdoc 中类型提示强制使用小写。
  • phpdoc_var_without_name: 移除 @var 标签中的变量名。
  • single_blank_line_at_eof: 在文件末尾添加一个空行。
  • single_class_element_per_statement: 每个语句只允许声明一个类成员。
  • single_import_per_statement: 每个 use 语句只允许导入一个类。
  • single_line_after_imports: 在 use 语句后添加一个空行。
  • single_line_comment_style: 单行注释的风格。
  • space_after_semicolon: 分号后的空格。
  • standardize_not_equals: 使用 <> 代替 !=
  • ternary_operator_spaces: 三元运算符周围的空格。
  • trailing_comma_in_multiline: 多行数组中允许使用尾随逗号。
  • trim_array_spaces: 移除数组中多余的空格。
  • unary_operator_spaces: 一元运算符周围的空格。
  • whitespace_after_comma_in_array: 数组中逗号后的空格。

你可以通过查阅 PHP-CS-Fixer 的官方文档来了解更多规则的详细信息:https://cs-fixer.friendsofphp.org/

3.4. 使用 PHP-CS-Fixer 查找并修复指定目录下的所有文件

./vendor/bin/php-cs-fixer fix --config .php-cs-fixer.dist.php  ./src

这条命令会使用 .php-cs-fixer.dist.php 文件中定义的规则,修复 src 目录下所有的 PHP 文件。

4. 将代码格式化工具集成到开发流程

为了确保代码风格的一致性,建议将代码格式化工具集成到开发流程中。以下是一些常用的方法:

  • IDE 集成: 许多 IDE (例如 PhpStorm、VS Code) 都提供了对 PHP-CS-Fixer 和 PHP Code Sniffer 的支持。你可以配置 IDE,使其在保存文件时自动运行代码格式化工具。
  • Git Hooks: 可以使用 Git Hooks 在提交代码之前自动运行代码格式化工具。如果代码风格不符合规范,则阻止提交。
  • 持续集成 (CI): 在 CI 系统中集成代码格式化工具,可以在每次代码提交时自动检查代码风格。如果代码风格不符合规范,则构建失败。

5. 如何选择合适的工具?

  • 对于新项目: 建议从一开始就使用 PHP-CS-Fixer,并配置好 .php-cs-fixer.dist.php 文件。
  • 对于现有项目: 可以先使用 PHP Code Sniffer 检测代码风格问题,然后使用 PHP-CS-Fixer 自动修复。
  • 如果需要更灵活的规则定制: 可以使用 PHP Code Sniffer 创建自定义规则集。
  • 如果追求自动化和效率: 建议使用 PHP-CS-Fixer。

6. 示例:一个更复杂的 .php-cs-fixer.dist.php 配置

<?php

use PhpCsFixerConfig;
use PhpCsFixerFinder;

$finder = Finder::create()
    ->in(__DIR__)
    ->exclude('var')
    ->exclude('node_modules')
    ->name('*.php')
    ->notName('index.php')
    ->ignoreDotFiles(true)
    ->ignoreVCS(true);

return (new Config())
    ->setFinder($finder)
    ->setRiskyAllowed(true)
    ->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' => [
            'default' => 'single_space',
            'operators' => ['=>' => null]
        ],
        'blank_line_after_opening_tag' => true,
        'blank_line_before_statement' => [
            'statements' => ['return']
        ],
        'cast_spaces' => true,
        'concat_space' => ['spacing' => 'one'],
        'declare_equal_normalize' => true,
        'elseif' => true,
        'encoding' => true,
        'full_opening_tag' => true,
        'function_declaration' => true,
        'function_typehint_space' => true,
        'heredoc_to_nowdoc' => true,
        'include' => true,
        'increment_style' => ['style' => 'post'],
        'indentation_type' => true,
        'line_ending' => true,
        'lowercase_constants' => true,
        'lowercase_keywords' => true,
        'method_argument_space' => true,
        'no_blank_lines_after_phpdoc' => true,
        'no_empty_phpdoc' => true,
        'no_empty_statement' => true,
        'no_extra_blank_lines' => true,
        'no_leading_import_slash' => true,
        'no_leading_namespace_whitespace' => true,
        'no_mixed_echo_print' => true,
        'no_multiline_whitespace_around_double_arrow' => true,
        'no_short_bool_cast' => true,
        'no_singleline_whitespace_before_semicolons' => true,
        'no_spaces_after_function_name' => true,
        'no_spaces_around_offset' => true,
        'no_spaces_inside_parenthesis' => true,
        'no_trailing_whitespace' => true,
        'no_unused_imports' => true,
        'no_whitespace_before_comma_in_array' => true,
        'no_whitespace_in_blank_line' => true,
        'normalize_index_brace' => true,
        'object_operator_without_whitespace' => true,
        'phpdoc_align' => true,
        'phpdoc_annotation_without_dot' => true,
        'phpdoc_indent' => true,
        'phpdoc_inline_tag_normalizer' => true,
        'phpdoc_no_access' => true,
        'phpdoc_no_package' => true,
        'phpdoc_no_useless_inheritdoc' => true,
        'phpdoc_scalar' => true,
        'phpdoc_separation' => true,
        'phpdoc_single_line_var_spacing' => true,
        'phpdoc_summary' => true,
        'phpdoc_to_comment' => true,
        'phpdoc_trim' => true,
        'phpdoc_types' => true,
        'phpdoc_var_without_name' => true,
        'single_blank_line_at_eof' => true,
        'single_class_element_per_statement' => true,
        'single_import_per_statement' => true,
        'single_line_after_imports' => true,
        'single_line_comment_style' => [
            'comment_types' => ['hash']
        ],
        'single_quote' => true,
        'space_after_semicolon' => true,
        'standardize_not_equals' => true,
        'ternary_operator_spaces' => true,
        'trim_array_spaces' => true,
        'whitespace_after_comma_in_array' => true,
    ])
    ->setUsingCache(true);

这个配置文件更加全面,涵盖了更多的代码风格规则。你可以根据自己的需要进行调整。

7. 总结

今天我们学习了如何使用 PHP-CS-Fixer 和 PHP Code Sniffer 来统一 PHP 代码风格。通过合理的配置和集成,我们可以显著提高代码的可读性、可维护性,并提升团队的协作效率。希望大家在实际开发中积极应用这些工具,编写出更加规范、高质量的 PHP 代码。

最后,选择合适的工具并将其集成到开发流程中,对于保持代码风格一致性至关重要。持续改进配置和规则,以适应团队的需求和项目的演变。

发表回复

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