代码风格指南


PSR-2 在 PSR-1 的基础上进行了继承和扩展



1. 概述

  • 代码 ​​必须​​ 遵循 ​​PSR-1​​ 规范
  • 代码 ​​必须​​ 使用 ​​4个空格​​ 的缩进,而不是制表符 ​​tab​
  • 一行代码长度 ​​不可​​ 有硬性限制,软限制必须为120个字符,也应当是80个字符或者更少
  • 在 ​​namespace​​ 声明以下 ​​必须​​ 有一个空行。而且 ​​use​​ 声明代码块以下也必须有一个空行
  • 类的開始花括号 ​​必须​​ 放到下一行,结束花括号 ​​必须​​ 放在类主体的下一行
  • 方法的開始花括号 ​​必须​​ 放在下一行,结束花括号 ​​必须​​ 放在方法主体以下
  • 全部的属性和方法的可见性 ​​必须​​ 显式(译者注:​​Public​​, ​​Protect​​, ​​Private​​)声明,​​abstract​​ 和 ​​final​​ 声明必须在显式声明可见性之前。​​static​​ 声明必须在显式声明可见性之后
  • 控制结构(译者注:​​for​​,​​while​​ 等)的关键词 ​​必须​​ 在后面有一个空格; 方法和函数 ​​必须​​ 没有
  • 控制结构(译者注:​​for​​,​​while​​ 等)的開始花括号 ​​必须​​ 放在同一行,结束花括号 ​​必须​​ 放在控制主体的下一行
  • 控制结构的左括号后面不可有空格。右括号之前不可有空格

1.1. 演示样例

对于上述规则的一些演示样例:

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
public function sampleFunction($a, $b = null)
{
if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}
}

final public static function bar()
{
// method body
}
}


2. 常规

2.1 基础编码规范

代码 ​​必须​​ 遵守 ​​PSR-1​​ 的全部规范

2.2 文件

全部的 PHP 文件 ​​必须​​ 使用 ​​Unix LF​​ (换行)作为行结束符

全部PHP文件 ​​必须​​ 以一个空行结束

仅仅有 PHP 代码的文件关闭标签 ​​?>​​ ​​必须​​ 省略

2.3 行

每行的长度 ​​不可​​ 有硬性限制

每行长度的软限制必须是 ​​120​​ 个字符。对于软限制。自己主动样式检查器 ​​必须​​ 警告但 ​​不可​​ 报错

每行实际长度 ​​不应该​​ 超过 ​​80​​ 个字符,较长的行 ​​应该​​ 被拆分成多个不超过 ​​80​​ 个字符的兴许行

在非空行后面 ​​不可​​ 有空格

空行 ​​能够​​ 用来改善可读性和区分相关的代码块

每行 ​​不可​​ 多于一个语句

2.4 缩进

代码 ​​必须​​ 使用 ​​4个空格​​ 的缩进。而且 ​​不可​​ 使用制表符 ​​tab​​ 作为缩进

注意:仅仅用空格。不与制表符 ​​tab​​ 混合使用,将会对避免代码差异。补丁,历史和注解中的一些问题有帮助。

使用空格还能够使调整细微的缩进来改进行间对齐变得简单

2.5 关键词 ​​keywords​​ 和 ​​True/False/Null​

PHP 的关键词 ​​keywords​​ ​​必须​​ 用小写

PHP 中的常量 ​​true​​。​​false​​,​​null​​ ​​必须​​ 全部小写



3. ​​Namespace​​ 和 ​​Use​​ 声明

假设存在。​​namespace​​ 声明后面 ​​必须​​ 有一个空行

假设存在,全部的 ​​use​​ 声明 ​​必须​​ 放在 ​​namespace​​ 声明以下

一个 ​​use​​ 关键字 ​​必须​​ 仅仅用于一个声明

​use​​ 声明代码块后面 ​​必须​​ 有一个空行

例:

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// ... additional PHP code ...


4. 类 ​​class​​,属性 ​​property​​,方法 ​​method​

类 ​​class​​ 指全部的类 ​​class​​。接口 ​​interface​​ 和特性 ​​trait​

4.1. 继承 ​​extends​​ 和接口实现 ​​implements​

一个类的 ​​extends​​ 和 ​​implements​​ 关键词 ​​必须​​ 和类名 ​​class name​​ 在同一行

类的開始花括号 ​​必须​​ 放在以下自成一行,结束花括号 ​​必须​​ 放在类主体的后面自成一行

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
// constants, properties, methods
}


接口实现 ​​implements​​ 的列表 ​​能够​​ 被拆分为多个有一次缩进的兴许行。

假设这么做,接口列表的第一个接口名 ​​必须​​ 要放在下一行,而且每行 ​​必须​​ 仅仅有一个接口。

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// constants, properties, methods
}


4.2. 属性 ​​property​

全部的属性 ​​必须​​ 显式声明可见性

​var​​ 关键词 ​​不可​​ 用来声明属性

一个语句 ​​不可​​ 声明多个属性

属性名称 ​​不应该​​ 使用单个下划线作为前缀来表明保护或私有的可见性

一个属性声明应该像这样:

<?php
namespace Vendor\Package;

class ClassName
{
public $foo = null;
}


4.3. 方法 ​​method​

全部的方法 ​​必须​​ 显式声明可见性

方法名 ​​不应该​​ 使用单个下划线作为前缀来表明保护或私有的可见性

方法名在声明之后 ​​不可​​ 尾随一个空格。

開始花括号 ​​必须​​ 放在以下自成一行,而且结束花括号 ​​必须​​ 放在方法主体的以下自成一行

左括号后面 ​​不可​​ 有空格。右括号前面 ​​不可​​ 有空格

一个方法定义应该像以下这样, 注意括号,逗号。空格和花括号:

<?php
namespace Vendor\Package;

class ClassName
{
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// method body
}
}


4.4. 方法參数 ​​Method Arguments​

參数列表中。逗号之前 ​​不可​​ 有空格。逗号之后 ​​必须​​ 要有一个空格

方法中有默认值的參数 ​​必须​​ 放在參数列表的最后面

<?php
namespace Vendor\Package;

class ClassName
{
public function foo($arg1, &$arg2, $arg3 = [])
{
// method body
}
}


參数列表 ​​能够​​ 被分为多个有一次缩进的多个兴许行。假设这么做,列表的第一项 ​​必须​​ 放在下一行,而且每行 ​​必须​​ 仅仅放一个參数

当參数列表被分为多行。右括号和左花括号 ​​必须​​ 夹带一个空格放在一起自成一行

<?php
namespace Vendor\Package;

class ClassName
{
public function aVeryLongMethodName(
ClassTypeHint $arg1,
&$arg2,
array $arg3 = []
) {
// method body
}
}


4.5. ​​abstract​​,​​final​​ 和 ​​static​

假设存在,​​abstract​​ 和 ​​final​​ 声明 ​​必须​​ 放在可见性声明之前

假设存在,​​static​​ 声明 ​​必须​​ 放在可见性声明后一个

<?php
namespace Vendor\Package;

abstract class ClassName
{
protected static $foo;

abstract protected function zim();

final public static function bar()
{
// method body
}
}


4.6. 方法 ​​method​​ 和函数 ​​function​​ 调用

当进行函数或方法调用的时候。在方法或者函数名与左括号之间 ​​不可​​ 有空格。左括号之后 ​​不可​​ 有空格。右括号之前 ​​不可​​ 有空格

參数列表中,逗号之前 ​​不可​​ 有空格,逗号之后 ​​必须​​ 有一个空格

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);


參数列表 ​​能够​​ 被拆分成多个有一个缩进的兴许行。假设这么做,列表中的第一项 ​​必须​​ 放在下一行,而且每一行 ​​必须​​ 仅仅有一个參数

<?php
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);


5. 控制结构 ​​Control Structures​

对于控制结构通常的样式规则例如以下:

  • 控制结构关键词之后 ​​必须​​ 有一个空格
  • 左括号之后 ​​不可​​ 有空格
  • 右括号之前 ​​不可​​ 有空格
  • 在右括号和開始花括号之间 ​​必须​​ 有一个空格
  • 代码主体 ​​必须​​ 有一次缩进
  • 结束花括号 ​​必须​​ 在主体的下一行

结构的主体部分 ​​必须​​ 被括在花括号中,这使结构体看起来更加标准。降低了在主体部分中增加新行时出现错误的可能

5.1. ​​if​​,​​elseif​​,​​else​

一个 ​​if​​ 结构看起来应该像以下这样。注意括号,空格,花括号的位置,而且 ​​else​​ 和 ​​elseif​​ 和前一个主体的结束花括号在同一行

<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body;
}


关键词 ​​elseif​​ ​​应该​​ 替代 ​​else if​​,以保持全部的控制关键词像一个单词

5.2. ​​switch​​,​​case​

一个 ​​switch​​ 结构看起来应该像以下这样。

注意括号,空格和花括号。​​case​​ 语句必须从 ​​switch​​ 处缩进。而且 ​​break​​ 关键字(或其它中止关键字)必须和 ​​case​​ 主体缩进在同级。假设一个非空的 ​​case​​ 主体往下落空(译者注:就是这个 ​​case​​ 不适用 ​​break​​ 结束)则必须有一个相似 ​​// no break​​ 的凝视

<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}


5.3. ​​while​​,​​do while​

一个 ​​while​​ 语句看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
while ($expr) {
// structure body
}


同样的。一个 ​​do while​​ 语句看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
do {
// structure body;
} while ($expr);


5.4. ​​for​

一个 ​​for​​ 语句看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
for ($i = 0; $i < 10; $i++) {
// for body
}


5.5. ​​foreach​

一个 ​​foreach​​ 语句看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
foreach ($iterable as $key => $value) {
// foreach body
}


5.6. ​​try​​,​​catch​

一个 ​​try catch​​ 语句看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}


6. 闭包 ​​Closures​

闭包在声明时 ​​function​​ 关键词之后 ​​必须​​ 有一个空格,而且 ​​use​​ 之前也须要一个空格

開始花括号 ​​必须​​ 与 ​​function​​ 在同一行,结束花括号 ​​必须​​ 在主体的下一行

參数列表和变量列表的左括号之后 ​​不可​​ 有空格,其右括号之前也 ​​不可​​ 有空格

在參数列表和变量列表中,逗号之前 ​​不可​​ 有空格,逗号之后 ​​必须​​ 有空格

闭包带默认值的參数 ​​必须​​ 放在參数列表后面

一个闭包声明看起来应该像以下这样。注意括号,空格和花括号的位置

<?php
$closureWithArgs = function ($arg1, $arg2) {
// body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
// body
};


參数和变量列表 ​​能够​​ 被分成多个带一次缩进的兴许行。假设这么做。列表的第一项 ​​必须​​ 放在下一行,而且一行 ​​必须​​ 仅仅放一个參数或变量

当终于列表(无论是參数还是变量)被分成多行。右括号和開始花括号 ​​必须​​ 夹带一个空格放在一起自成一行。

以下是一个參数和变量列表被切割成多行的演示样例:

<?php
$longArgs_noVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) {
// body
};

$noArgs_longVars = function () use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};

$longArgs_longVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};

$longArgs_shortVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use ($var1) {
// body
};

$shortArgs_longVars = function ($arg) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};


注意假设在函数或者方法中把闭包作为一个參数调用,上面的样式规则也适用

<?php
$foo->bar(
$arg1,
function ($arg2) use ($var1) {
// body
},
$arg3
);


7. 结论

该指南中有非常多风格的元素和做法被有益忽略掉。这些包含以下的等等:

  • 全局变量和全局常量的声明
  • 方法声明
  • 操作符和赋值
  • 行间对齐
  • 凝视和文档块
  • 类名给你前缀和后缀
  • 最佳实践


敲了快两个小时。

。要疯了(生无可恋)。。