在项目和团队之间共享 PHP-CS-Fixer 规则

发布时间 作者

Sharing PHP-CS-Fixer rules across projects and teams image

PHP-CS-Fixer 是一款开源工具,可以强制执行和检测 PHP 代码风格的违规行为。通过预定义的规则,它允许您拥有严格的代码风格,由工具强制执行,以便您将更多时间花在更重要的事情上。

规则示例

以下是一些 PHP-CS-Fixer 可以对您的代码库进行的操作示例。

规则:is_null

$var === null 替换 is_null($var) 表达式。

// before...
if (is_null($account->closed_at)) {
//
}
 
// after...
if ($account->closed_at === null) {
//
}

规则:mb_str_functions

用相应的 mb 函数替换非多字节安全的函数。

// before...
$length = strlen($request->post('slug'));
 
// after...
$length = mb_strlen($request->post('slug'));

规则:not_operator_with_successor_space

逻辑 NOT 运算符 (!) 应该带有一个尾随空格。

// before...
- if (!$user->is_active) {
//
}
 
// after...
if (! $user->is_active) {
//
}

可用的规则非常全面,并且数量还在不断增加。您可以在 项目的自述文件 中查看所有可用的规则列表。您可能还想查看 PHP-CS-Fixer 配置器,这是一个网站,它提供每个规则的示例,以防它们的描述不清楚。

小贴士:除了修复样式之外,它通常可以作为升级工具。 PHPUnit 8 为多个方法添加了 void 返回类型。在 /tests 目录上运行 PHP-CS-Fixer 的 void_return 规则可以立即升级您的测试套件,使其与这些更改兼容。

共享您的规则

我在我的所有项目中都使用 PHP-CS-Fixer,并且有一个规则集来定义样式。到目前为止,我一直都是在我开始新项目时复制粘贴我的规则,并且随着新规则的发布,我必须更新我所有现有项目中的配置。这不是一个理想的工作流程,因为您很容易忘记更新特定项目,而且这是一堆手动工作。

事实证明,您可以在多个项目和团队之间共享您的规则,以便 composer update 将在任何时候让您的所有项目使用您规则集的最新版本。

搭建仓库

我们将构建一个 git 仓库来存放我们的共享规则集。要开始,我们将初始化一个本地 git 仓库并创建所需的配置文件。

$ mkdir php-styles
 
$ cd php-styles
 
$ git init
 
$ echo "/composer.lock
/vendor
/.php_cs.cache" >> .gitignore
 
$ mkdir src
 
$ touch src/rules.php src/helpers.php composer.json

定义您的规则

正如我之前提到的,有一套广泛的规则,并且新版本有时包含新规则,因此我发现跟踪您上次查看可用规则的 PHP-CS-Fixer 版本非常有用。这意味着当您升级到新版本时,您将知道要查看哪些版本以查找您可能希望添加到共享规则集中的新规则。我喜欢将上次查看的版本添加到 rules.php 文件的顶部。

<?php
 
// last reviewed: v2.16.3 Yellow Bird

接下来,我们要让 rules.php 文件返回一个包含我们规则集的数组。将规则放在单独的文件中很方便,因为根据您的规格,列表可能会变得非常长。它还允许其他开发人员拉取您的规则集并将它们与他们自己的规则集合并,例如,如果您想拉取 Laravel 代码标准并将其与您团队的一些额外标准组合起来。

<?php
 
// last reviewed: v2.16.3 Yellow Bird
 
return [
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'final_class' => false,
'new_with_braces' => true,
// ...
];

PHP-CS-Fixer 带有一些预定义的规则集。与 PSR-2 标准相关的所有规则都捆绑在规则集 @PSR2 中。这允许我们选择标准,而无需单独指定每个规则。

某些规则与其选项相关联。array_syntax 规则允许您指定是否要使用短数组语法或长数组语法。

其他规则在列表中通过使用它们的名称和一个布尔值来指定,如 new_with_braces 规则所示。虽然您可以省略布尔值,但我喜欢将其包含在内以保持一致性,因此数组中的每个项都是一个 key ⇒ value 对,因此我知道我已经明确地排除了特定规则。

辅助方法

为了使在您的项目中使用您的共享规则变得轻松,我们将创建一个辅助函数。您可能现在还不知道为什么要这样做,但请继续关注,一切都会水到渠成。

为了确保该函数不会与您项目或其依赖项中的任何其他全局函数发生冲突,最好将该函数放在命名空间中。打开 helpers.php 文件并定义一个适合您的上下文的命名空间。

<?php
 
namespace TiMacDonald;

现在我们需要定义方法签名。该方法将接受一个 PhpCsFixer\Finder 实例,以及一个规则数组,这将允许项目识别每个项目的基础上任何额外的强制规则。通常,我会说我们想要一致性,并且不应该允许每个项目更改共享规则集——但我不会在这里告诉你该怎么做,所以我们会让你这样做,但你始终可以删除该功能,如果这是你的偏好。

<?php
 
namespace TiMacDonald;
 
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
 
function styles(Finder $finder, array $rules = []): Config {
//
}

太棒了。它正在很好地组合在一起。现在最后要做的事情是填充辅助函数的主体。

<?php
 
namespace TiMacDonald;
 
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
 
function styles(Finder $finder, array $rules = []): Config {
$rules = array_merge(require __DIR__.'/rules.php', $rules);
 
return Config::create()
->setFinder($finder)
->setRiskyAllowed(true)
->setRules($rules);
}

$finder 是 PHP-CS-Fixer 知道在哪里查找要修复的 PHP 文件的方式。我们将此决定推迟到项目,因为每个项目可能具有不同的目录结构,例如,Laravel 项目与 Laravel 包相比。

危险规则

styles 函数的主体中,您可以看到我们正在告诉配置允许“危险”规则,通过调用 setRiskyAllowed(true)。您必须阅读文档并了解危险规则如何影响您的项目。例如,我们来看一下 implode_call 规则。如果您阅读了 PHP 文档关于 implode 的内容,您会注意到

implode() 由于历史原因,可以接受其参数以任意顺序排列。但是,为了与 explode() 保持一致性,不使用文档中指定的参数顺序已被弃用。

这意味着这两个 implode 调用将产生相同的结果

<?php
 
implode($array, ',');
 
implode(',', $array);

implode_call 规则将重新排列参数以使其按文档顺序排列,但如果您的项目通过某种方式(例如 runkit)重新定义了 implode() 的行为以按错误顺序预期参数,则更改其顺序可能会破坏您的代码。

因此,请阅读每个危险规则的作用,并了解其工作原理,然后再将其添加到您的规则集中。

composer.json

为了将包拉取到我们的项目中,我们需要填充 composer.json 文件。我建议在持续集成(C.I.)中运行样式检查,因此我将本地包含 PHP-CS-Fixer(如果您有包冲突,您可以选择将 PHP-CS-Fixer 下载为 Phar 文件)。

打开 composer.json 文件,并确保设置一个适合您的唯一 "name"

{
"name": "timacdonald/php-style-example",
"description": "Tim's shared PHP style rules for PHP-CS-Fixer",
"license": "MIT",
"require": {
"friendsofphp/php-cs-fixer": "^2.0"
},
"autoload": {
"files": [
"./src/helpers.php"
]
}
}

将代码推送到代码托管平台

设置代码仓库的最后一步是将其推送到托管的 Git 解决方案。在您选择的代码托管平台上创建一个仓库,并将其添加为本地仓库的远程仓库。我将使用 GitHub。

$ git add .
 
$ git commit -m wip
 
$ git remote add origin [email protected]:timacdonald/php-style-example.git
 
$ git push -u origin master

现在,我们已将共享的规则包发布到 GitHub 上。恭喜!

使用共享规则

现在我们将稍微改变方向,重点介绍如何在其他项目中使用新的共享规则。关闭共享规则仓库,并打开要使用这些规则的项目。有一些初始设置,但完成之后,只需要运行 composer update 命令即可。

引入仓库

Composer 允许我们从托管的 Git 平台引入仓库,而无需将它们提交到 Packagist。考虑到这种类型的仓库很可能是内部的,将其添加到 Packagist 并没有太大好处。

要开始使用,请手动将包名称添加到项目的 "require-dev" 块中。我不需要将我的样式锁定到特定版本,因此我使用 "dev-master",这意味着始终会拉取最新的样式。但是,您也可以对样式进行版本控制,这取决于您。

由于我们不会提交到 Packagist,因此必须告诉 Composer 在哪里找到包。我们使用 repositories 块来实现这一点。

"repositories": [
{
"type": "vcs",
"url": "https://github.com/timacdonald/php-style-example"
}
]

现在,我们告诉 Composer 将我们的包作为 --dev 依赖项引入。

$ composer require timacdonald/php-style-example --dev

设置 PHP-CS-Fixer Finder 配置

为了让 PHP-CS-Fixer 知道要针对哪些文件,您需要使用 PhpCsFixer\Finder 实例指定每个目录或文件。这是 Symfony\Component\Finder\Finder 的继承版本,因此有关所有可使用约束的完整文档,请 查看文档

在我们的示例中,我将假装我们正在使用 Laravel 应用程序,并设置 Finder 以搜索我知道要遵守样式规范的目录。

PHP-CS-Fixer 预计您的配置位于 /.php_cs.dist 文件中,因此我们将创建该文件。

$ touch .php_cs.dist

打开此文件并添加以下 Finder 设置,适用于您的 Laravel 应用程序。您也可以包含任何其他要修复的文件夹,但这些是合理的默认值。

<?php
 
$finder = PhpCsFixer\Finder::create()
->in([
__DIR__.'/app',
__DIR__.'/config',
__DIR__.'/database',
__DIR__.'/routes',
__DIR__.'/tests',
]);

现在,我们准备好将 Finder 传递给几分钟前创建的辅助函数。PHP-CS-Fixer 预计此文件将返回 PhpCsFixer\Config 的实例,这正是我们的辅助函数返回的内容。

<?php
 
$finder = PhpCsFixer\Finder::create()
->in([
__DIR__.'/app',
__DIR__.'/config',
__DIR__.'/database',
__DIR__.'/routes',
__DIR__.'/tests',
]);
 
return TiMacDonald\styles($finder);

现在准备好姿势,我们将自动修复所有这些目录中的编码风格!进入终端并运行以下命令以观察奇迹发生……

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

在 CI 中运行

在 CI 过程中执行样式规则是一个好主意。您可以通过几种方式实现:您可以进行“试运行”,如果检测到代码风格违规,则会失败。

./vendor/bin/php-cs-fixer fix --dry-run

或者,您可以让 CI 运行修复器并自动将更改提交到您的仓库。如果您使用 GitHub Actions,请 查看 Stefan Zweifel 撰写的这篇很棒的文章,了解如何实现这一点。

总结

感谢您参与这段旅程。PHP-CS-Fixer 是一款很棒的工具,如果您运行多个共享标准编码风格的项目,那么这种方法可能会派上用场。

timacdonald photo

专注于 TDD,开发引人入胜且性能优良的 Web 应用程序。专门从事 PHP/Laravel 项目。❤️ 为 Web 构建。

归档于
Cube

Laravel 时事通讯

加入 40,000 多名其他开发人员,永远不要错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

无妥协

Joel 和 Aaron,两位来自无妥协播客的经验丰富的开发人员,现在可以为您的 Laravel 项目聘用。 ⬧ 固定价格 7500 美元/月。 ⬧ 无漫长的销售流程。 ⬧ 无合同。 ⬧ 100% 返款保证。

无妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

正在运行旧版本的 Laravel?即时、自动的 Laravel 升级和代码现代化,使您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

聘用经验丰富的 Laravel 开发人员,拥有 4-6 年的经验,每月只需 2500 美元,即可为您的项目注入活力。获得 160 小时的专业技能和 15 天的无风险试用期。立即安排电话会议!

Bacancy
Lucky Media logo

Lucky Media

立即获得好运 - 拥有十多年经验,是 Laravel 开发的理想选择!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

Laravel 的电子商务。一个开源包,将现代无头电子商务功能的强大功能带入 Laravel。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 工作板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,包含运行现代 SaaS 所需的所有功能。支付、精美结帐、管理面板、用户仪表板、身份验证、即用型组件、统计信息、博客、文档等。

SaaSykit:Laravel SaaS 启动工具包
Rector logo

Rector

您的合作伙伴,帮助您顺利升级 Laravel、降低成本并加快创新,助力公司取得成功

Rector
MongoDB logo

MongoDB

通过 MongoDB 和 Laravel 的强大集成,增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 灵活、现代的数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

在您的 Laravel 应用程序中添加 Swagger UI

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel 提示构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包在您的 Laravel 应用程序中添加评论

阅读文章