bit3/php-coding-standard

该软件包已被废弃且不再维护。作者建议使用 contao-community-alliance/coding-standard 软件包。

bit3 PHP 编码规范

安装数: 1,717

依赖项: 27

建议者: 0

安全: 0

星标: 2

关注者: 4

分支: 0

类型:coding-standard

2.4 2013-11-29 04:08 UTC

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 phpmdant phpcs 来运行测试。运行 antant 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* 多行注释

类和函数声明

对于所有非控制结构,如类或函数声明,将开括号 { 放在新的一行上。将 extendsimplements 放在新的一行上,并缩进一次。

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 ...
);

不要忘记在开括号 ( 前面留空格。

三元运算符

使用三元运算符时,应将 thenelse 部分放在单独的行上,如果行过长,则缩进一次。

// 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);