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 来安装这两个工具。
-
全局安装 (推荐):
composer global require friendsofphp/php-cs-fixer composer global require squizlabs/php_codesniffer全局安装后,你可以在任何目录下直接使用
php-cs-fixer和phpcs命令。 -
项目内安装:
在你的项目目录下运行:
composer require --dev friendsofphp/php-cs-fixer composer require --dev squizlabs/php_codesniffer项目内安装后,你需要使用
vendor/bin/php-cs-fixer和vendor/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 项目的代码风格规范。
你可以使用内置的标准,也可以自定义规则集。
-
使用内置标准:
假设我们想使用 PSR-12 标准来检查代码,可以使用以下命令:
phpcs --standard=PSR12 your_file.php phpcs --standard=PSR12 your_directory/your_file.php和your_directory/是你要检查的文件或目录。 -
自定义规则集 (
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')表示排除var和vendor目录。
-
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 集成到你的开发流程中。
-
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/phpcs和vendor/bin/php-cs-fixer替换为phpcs和php-cs-fixer。 -
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 会失败。 -
IDE 集成:
许多 IDE (例如 PHPStorm, VS Code) 提供了对 PHP-CS-Fixer 和 PHPCS 的集成。你可以配置 IDE 在保存文件时自动运行 PHP-CS-Fixer,或者在代码编辑器中显示 PHPCS 的警告和错误信息。
处理大型项目的代码风格迁移
对于已经存在的大型项目,进行代码风格迁移可能会比较困难。建议采取以下步骤:
- 逐步迁移: 不要试图一次性修复所有代码。可以先从一部分代码开始,逐步扩大范围。
- 制定明确的规则: 在开始迁移之前,制定明确的代码风格规范,并将其写入文档。
- 使用工具: 充分利用 PHP-CS-Fixer 和 PHPCS 的功能,尽可能自动化修复过程。
- 团队协作: 与团队成员沟通,确保每个人都理解并接受新的代码风格规范。
- 代码审查: 在迁移过程中,进行代码审查,确保代码风格的一致性。
总结
PHP-CS-Fixer 和 PHP Code Sniffer 是 PHP 代码格式化的两个利器。通过合理配置和使用这两个工具,可以有效地统一团队的代码风格,提高代码质量和可维护性,并最终提升开发效率。 记住,代码风格不仅仅是美观,更是代码质量的体现。