bit3 / php-coding-standard
Requires
- phpmd/phpmd: ~1.4
- squizlabs/php_codesniffer: ~1.4
This package is not auto-updated.
Last update: 2022-02-01 12:26:15 UTC
README
这是我们编码规范。
本编码规范基于优秀的 TYPO3 编码规范,请参阅 http://forge.typo3.org/projects/team-php_codesniffer/wiki/Using_the_TYPO3_Coding_Standard
哲学
我们的哲学:编写快速、易读、易懂的代码。不要害羞地写更多行,如果它使每行更原子化。
原子行的好处是什么?当每行都是全原子(仅包含一个操作)时,行的顺序反映了命令的执行顺序。
当您有一行复杂的代码如下
$variable = ($foo != $bar && count($zap) || $dig) ? $this->func($zap, $foo, $bar) : $this->other(count($zap))->chain($foo, $bar);
执行顺序如何?这段代码做什么?您可以通过分析这行代码来理解,但这很难做。简化后,这是操作的执行顺序
evaluate $foo != $bar
execute count($zap)
evaluate count($zap)
evaluate .. && ..
evaluate $zip
evaluate .. || ..
if true
execute $this->func($zap, $foo, $bar)
else
execute count($zap)
evaluate count($zap)
execute $this->other(count($zap))
execute $..->chain($foo, $bar)
assign $variable
如果您想理解这段代码做什么,您必须理解操作的执行顺序和每个操作的意义。如果您以更原子化的风格编写,这将使代码更容易理解,对他人和自己来说,如果长时间不接触代码,将更容易理解!
与以下代码比较,它是完全相同的代码
if ( $foo != $bar && count($zap) || $dig ) { $variable = $this->func($zap, $foo, $bar); } else { $variable = $this->other(count($zap))->chain($foo, $bar); }
如您所见,这个片段更反映了执行顺序,并且更容易理解它做什么。
用法
通过 composer 安装编码规范
"require-dev":{ "bit3/php-coding-standard":"@dev" }
更新依赖项后,将 vendor/bit3/php-coding-standard/example/build.xml 中的示例 ant build 文件复制到您的项目中。如果您的源代码不在 src/
中,请在 build 文件中更改到您的源代码的路径。
提示:如果您不使用 phpunit,请从 build 文件中删除 phpunit 目标。
您可以通过调用 ant phpmd
和 ant phpcs
来运行测试。运行 ant
或 ant test
将运行所有测试目标。
提示:要运行所有测试,即使有一个失败,也使用 ant -keep-going
。
定义
- 长行指的是超过 60 个字符的行。
- 任何行都不应超过 100 个字符。
- 任何行都不应超过 120 个字符。
文件
任何文件都不应包含多于一个类、接口或函数。文件名必须与其中定义的类、接口或函数的名称相同(包括大小写)。不包括任何前缀(例如 class.
)或后缀(例如 .inc
),除非是文件类型扩展 .php
。
运行脚本应包含一个运行类,其中包含一个 run
方法。
示例 index.php
<?php require_once('autoload.php'); class index { public function run() { // runtime code } } $index = new index(); $index->run();
提示:运行类不应使用 Pascal-case,而应与文件名匹配。
第二个示例 ajax.php
<?php class ajax { public function run() { // runtime code } } $ajax = new ajax(); $ajax->run();
空白
**不要**使用 空格
进行缩进。使用 制表符
。
添加空格以分隔运算符
- 赋值:
$variable = 'value'
- 参数:
func($a, $b, $c)
- 数组:
array('foo' => 'bar', 'bar' => 'foo')
- 注释:
// comment
或* 多行注释
类和函数声明
对于所有非控制结构,如类或函数声明,将开括号 {
放在新的一行上。将 extends
和 implements
放在新的一行上,并缩进一次。
class Foo extends Bar implements Zap { public function func() { ... } }
function func() { ... }
在函数声明或调用中不要在开括号 (
前面加空格。
命名
使用 Pascal-case 类名。
// bad class foo_bar { } // good class FooBar { }
使用 camel-case 方法名。
// bad function foo_bar() { } // good function fooBar() { }
控制结构
对于所有控制结构,将开括号 {
放在同一行上。在闭括号 }
后添加换行,即使控制结构继续。
if (...) { ... } else if (...) { ... } else { ... }
for (...) { ... }
foreach (...) { ... }
while (...) { ... }
do { ... } while (...);
为什么将 else
放在新的一行上?很简单,首先它是新块的开头。其次,它更容易添加描述条件的注释。
// describe if condition if (...) { ... } // describe else if condition else if (...) { ... } // describe else condition else { ... }
长和多行条件
如果控制结构条件过长,请将闭括号和开括号 ) {
放在单独的一行上,并将条件放在单独的一行上。
if ( ... very long ... ... multiline ... ) { ... } else if ( ... very long ... ... multiline ... ) { ... } else { ... }
for ( ... very long ... ... multiline ... ) { ... }
foreach ( ... very long ... ... multiline ... ) { ... }
while ( ... very long ... ... multiline ... ) { ... }
do { ... } while ( ... very long ... ... multiline ... );
不要忘记在开括号 (
前面留空格。
三元运算符
使用三元运算符时,应将 then
和 else
部分放在单独的行上,如果行过长,则缩进一次。
// good $variable = $if ? $then : $else; // good $variable = $if ? $this->then() : $this->else(); // bad $variableObjectname = $someLongVariable != $otherLongVariable ? $veryLongVariableName : $anotherVeryLongVariableName; // good $variableObjectname = $someLongVariable != $otherLongVariable ? $veryLongVariableName : $anotherVeryLongVariableName;
三元运算符应仅用于简单的左右决策。不要与复杂条件或逻辑结合使用。
// bad, use formated if-statement instead $variable = $firstVariable != $secondVariable && someCheckFunction($variableName) || anotherCheckFunction($thirdVariable) ? $this->someComplexFunction($firstVariable, $secondVariable, $thirdVariable) : 'some string prefix ' . substr($this->otherComplexFunction($variablename), 0, strlen($thirdVariable)) . ' some string suffix'; // good $variable = $firstVariable != $secondVariable ? $this->then() : $this->else(); // good $variable = someCheckFunction($variableName) ? $then : $else;
函数/方法调用
在函数/方法调用中使用空格来分隔参数,但不要在开括号 (
前面加空格。
// bad func ('a','b','c'); // good func('a', 'b', 'c');
当参数列表过长时,将其分成多行,并将每个参数放在单独的一行上。还要将闭括号 )
放在单独的一行上。
// bad func ('short', 'short', 'very long param'); // good func( 'short', 'short', 'very long param' );
在链式方法调用中,如果合理或行过长,则将每个方法调用放在单独的一行上。
// bad
$database->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')->limit(100)->offset(50)->execute();
// a little bit better
$database->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')
->limit(100)->offset(50)->execute();
// good
$database
->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')
->limit(100)
->offset(50)
->execute();
变量
初始化
将复杂的数组初始化分成多行,并将每个元素放在单独的一行上。
$array = array( 'item1', 'item2', 'item3', );
$array = array( 'index1' => 'item1', 'index2' => 'item2', 'index3' => 'item3', );
命名
使用 camel-case 变量名。使用有意义的变量名而不是类型前缀。
// bad $intUser = 1; // good $userId = 1;
// bad $objUser = ...some object...; // good $user = ...some object...;
// bad $arrUsers = array(1, 2, 3); // good $userIds = array(1, 2, 3);
// bad $arrUsers = array(...object..., ...object..., ...object...); // good $users = array(...object..., ...object..., ...object...);
逻辑
尽可能使每行保持简单,不要在一行中组合过多的操作。如果需要,使用可读的控制结构,即使你写 很多 行!
// bad $variable = ($foo != $bar && count($zap) || $dig) ? $this->func($zap, $foo, $bar) : $this->other(count($zap))->chain($foo, $bar); // good $n = count($zap); if ( $foo != $bar && $n || $dig ) { $variable = $this->func($zap, $foo, $bar); } else { $variable = $this->other($n)->chain($foo, $bar); }
不要在函数调用参数中使用逻辑。
// bad func( $if ? $then : $else, 'foo', other('bar') ); // good $param = $if ? $then : $else; $other = other('bar'); func( $param, 'foo', $other );
小心使用函数或方法链,但尽可能保持其简单性。
// avoid illogical chaining // $this->func, strlen and file_get_contents does not logical belongs to each other $this->func(strlen(file_get_contents('/some/file'))); // better $content = file_get_contents('/some/file'); $this->func(strlen($content)); // best $content = file_get_contents('/some/file'); $length = strlen($content); $this->func($length);
// be gentle with logical chaining // the array_* functions are logical belongs to each other, // but its hard to understand this at a glance $result = array_values(array_filter(array_map('trim', $array))); // better $result = array_values( array_filter( array_map( 'trim', $array ) ) ); // best, keep it simple, fast readable and more comprehensible - and it is short :-) $result = array_map('trim', $array); $result = array_filter($result); $result = array_values($result);