bmitch / codor
自定义PHPCS sniffs以查找代码异味。
Requires
- php: >=7.1.3
- squizlabs/php_codesniffer: ^3.2.3
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-18 01:02:13 UTC
README
👃 💩 自定义PHP代码嗅探器sniffs,帮助查找代码异味(臭味)。
灵感来源: https://github.com/object-calisthenics/phpcs-calisthenics-rules
这是什么?
本包是一组自定义的Sniffs,用于PHP Code Sniffer,您可以在CI构建中使用它以确保代码库的完整性。
兼容性
- PHP 7.1+ 请使用v1.0.0及以上版本。
- PHP 5.6及以下请使用v1.0.0以下任何版本。
如何安装?
通过Composer安装
composer require bmitch/codor --dev
如何使用?
在项目的根目录下创建一个PHPCS规则集XML(codor.xml
或您想要的任何文件名)文件。
<?xml version="1.0" encoding="UTF-8"?> <ruleset name="Project"> <description>Project Coding Standard</description> <rule ref="vendor/bmitch/codor/src/Codor/ruleset.xml"/> </ruleset>
然后使用以下命令运行它:
vendor/bin/phpcs --standard=codor.xml src
其中src
是您要检查的源代码位置。
省略sniffs
您可能不想运行提供的所有sniffs,因此可以使用--exclude
标志指定要排除的sniffs,例如:
vendor/bin/phpcs --standard=codor.xml --exclude=Codor.ControlStructures.NoElse src
(如果要排除多个,只需用逗号分隔即可)
运行特定sniffs
或者,您也可以指定要运行的特定sniffs
vendor/bin/phpcs --standard=codor.xml --sniffs=Codor.ControlStructures.NoElse src
在特定代码片段上抑制sniffs
请参阅PHPCS文档
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-files-and-folders
包含的sniffs
Codor.ControlStructures.NoElse
不允许任何else
或elseif
语句。
❌
if ($foo) { return 'bar'; } else { return 'baz'; }
✅
if ($foo) { return 'bar'; } return 'baz';
Codor.Files.FunctionLength
函数/方法不得超过20行。
❌
public function foo() { // more than 20 lines }
✅
public function foo() { // no more than 20 lines }
Codor.Files.FunctionParameter
函数/方法不得超过3个参数。
❌
public function foo($bar, $baz, $bop, $portugal) { // }
✅
public function foo($bar, $baz, $bop) { // }
Codor.Files.ReturnNull
函数/方法不得返回null
。
❌
public function getAdapter($bar) { if ($bar === 'baz') { return new BazAdapter; } return null; }
✅
public function getAdapter($bar) { if ($bar === 'baz') { return new BazAdapter; } return NullAdapter; }
Codor.Files.MethodFlagParameter
函数/方法不能有默认为布尔值的参数。
❌
public function getCustomers($active = true) { if ($active) { // Code to get customers from who are active } // Code to get all customers }
✅
public function getAllCustomers() { // Code to get all customers } public function getAllActiveCustomers() { // Code to get customers from who are active }
Codor.Classes.ClassLength
类不得超过200行。
❌
class ClassTooLong { // More than 200 lines }
✅
class ClassNotTooLong { // No more than 200 lines }
Codor.Classes.ConstructorLoop
类构造函数不能包含任何循环。
❌
public function __construct() { for($index = 1; $index < 100; $index++) { // foo } }
✅
public function __construct() { $this->someMethod(); } private function someMethod() { for($index = 1; $index < 100; $index++) { // foo } }
Codor.Classes.Extends
如果类继承另一个类,则发出警告。目标是促进组合而非继承(https://en.wikipedia.org/wiki/Composition_over_inheritance)。
❌
class GasolineCar extends Vehicle { // } class GasolineVehicle extends Vehicle { // }
✅
class Vehicle { private $fuel; public function __construct(FuelInterface $fuel) { $this->fuel; } } class Gasoline implements FuelInterface { } $gasolineCar = new Vehicle($gasoline);
Codor.Classes.FinalPrivate
最终类不应包含受保护的函数或变量。应使用private。
❌
final class Foo { protected $baz; protected function bar() { // } }
✅
final class Foo { private $baz; private function bar() { // } }
Codor.Classes.NewInstance
类不应实例化对象。应使用依赖注入。
❌
class NewInConstructor { private MyClass $myClass; public function __construct() { $this->myClass = new MyClass(); } }
✅
class NewInConstructor { private MyClass $myClass; public function __construct(MyClass $myClass) { $this->myClass = $myClass; } }
Codor.Classes.PropertyDeclaration
如果您的类使用未声明的成员变量,则产生错误。如果类继承自另一个类,则只发出警告。
❌
class Foo { private function bar() { $this->baz = 13; } }
✅
class Foo { private $baz; private function bar() { $this->baz = 13; } }
Codor.Files.FunctionNameContainsAndOr
函数/方法不能包含"And"或"Or"。这可能是函数执行多项任务的迹象。
❌
public function validateStringAndUpdateDatabase() { // code to validate string // code to update database }
✅
public function validateString() { // code to validate string } public function updateDatabase() { // code to update database }
Codor.Files.IndentationLevel
函数/方法不能有超过2层的缩进。
❌
public function foo($collection) { foreach ($collection as $bar) { foreach ($bar as $baz) { // } } }
✅
public function foo($collection) { foreach ($collection as $bar) { $this->process($bar); } } private function process($bar) { foreach ($bar as $baz) { // } }
Codor.ControlStructures.NestedIf
不允许嵌套的if语句。
❌
public function allowedToDrink($person) { if ($person->age === 19) { if ($person->hasValidId()) { return true; } } return false; }
✅
public function allowedToDrink($person) { if ($person->age !== 19) { return false; } if (! $person->hasValidId()) { return false; } return true; }
Codor.Syntax.NullCoalescing
如果一行包含可以转换为空合并操作符的三元运算符,则产生错误。
❌
$username = isset($customer['name']) ? $customer['name'] : 'nobody';
✅
$username = $customer['name'] ?? 'nobody';
Codor.Syntax.LinesAfterMethod
只允许函数/方法之间有1行。超过1行将产生错误。
❌
public function foo() { // } public function bar() { // }
✅
public function foo() { // } public function bar() { // }
Codor.TypeHints.MixedReturnType
阻止您在文档块中返回mixed
类型。
❌
/** * @return mixed */ public function foo() { // }
✅
/** * @return string */ public function foo() { // }
自定义sniffs
一些嗅探规则可以根据您的喜好进行自定义。例如,如果您希望 Codor.Files.FunctionLength
确保您的函数行数不超过30行而不是20行,您可以这样做。以下是一个带有该自定义的 codor.xml
文件示例
<?xml version="1.0" encoding="UTF-8"?> <ruleset name="Project"> <description>Project Coding Standard</description> <rule ref="vendor/bmitch/codor/src/Codor/ruleset.xml"/> <rule ref="Codor.Files.FunctionLength"> <properties> <property name="maxLength" value="30"/> </properties> </rule> </ruleset>
可用的自定义
Codor.Files.FunctionLength
maxLength
:一个函数/方法可以拥有的最大行数(默认 = 20)。Codor.Files.FunctionParameter
maxParameters
:一个函数/方法可以拥有的最大参数数(默认 = 3)。Codor.Classes.ClassLength
maxLength
:一个类可以拥有的最大行数(默认 = 200)。Codor.Files.IndentationLevel
indentationLimit
:缩进数不能超过或等于这个数值(默认 = 2)。
类似包
- https://github.com/object-calisthenics/phpcs-calisthenics-rules
- https://github.com/slevomat/coding-standard
贡献
请参阅 CONTRIBUTING.md
许可证
MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件