PSR-2 编码风格指北

Psr-2.jpg

编码风格指北

本规范是 PSR-1 基本编码规范的继承与扩展。

本规范的价值在于我们都遵循这个编码风格,而不是在于它本身。

1. Overview

  • 代码 必须 遵循 PSR-1 中的编码规范。
  • 代码 必须 使用 4 个空格符而不是「Tab 键」进行缩进。
  • 行的长度 一定不可 有硬性的约束;软性的约束 必须 限制在 120 个字符以内;行的长度 应该 少于 80 个字符。
  • namespace 命名空间声明语句和 use 声明语句后面,必须 插入一个空白行。
  • 类的「开始花括号」(opening braces) { 必须 写在类声明后自成一行,「结束花括号」(closing braces) }必须 写在类主体之后自成一行。
  • 方法的「开始花括号」 { 必须 写在方法声明后自成一行,「结束花括号」 }必须 写在方法主体之后自成一行。
  • 类的属性和方法 必须 声明「访问控制符」( Visibility ); abstractfinal 必须 声明在「访问控制符」之前,而 static 必须 声明在「访问控制符」之后。
  • 控制结构的关键字后 必须 要有一个空格符,而调用方法或函数时则 一定不可 有。
  • 控制结构的「开始花括号」 { 必须 写在声明的同一行,而「结束花括号」 } 必须 写在主体后自成一行。
  • 控制结构的「开始圆括号」(opening parentheses) ( 之后 和「结束圆括号」(closing parentheses) ) 之前,都 一定不可 有空格符号。

1.1. Example

本范例作为下文规则的快速概览:

<?php
namespace Vendor\Package;

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

class Foo extends Bar implements FooInterface
{
    public function sampleMethod($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }
    
    final public static function bar()
    {
        //方法主体
    }
}

2. 常规(General)

2.1. 基本编码规范

代码 必须 遵循 PSR-1 中的所有规范。

2.2. File

所有 PHP 文件 必须Unix LF( linefeed ) 作为行的结束符。

所有 PHP 文件 必须 以一行空白行作为结束。

纯 PHP 文件 必须 省略最后的 ?> 结束标签。

2.3. 行

行的长度 一定不可 有硬性的约束。

软性的长度约束 必须 要限制在 120 个字符以内,若超过此长度,带代码规范检查的编辑器 必须 要发出警告,不过 一定不可 发出错误提示。

每行 不该 多于 80 个字符,大于 80 字符的行 应该 折成多行。

非空行后 一定不可 有多余的空格符。

空行 可以 使得阅读代码更加方便以及有助于代码的分块。

每行 一定不可 存在多于一条语句。

2.4. 缩进(Indenting)

代码 必须 使用 4 个空格来进行缩进,并且 一定不能 使用 tab 键来缩进。

注意:仅使用空格,而不是使用空格和 tab 键混在一起,能帮助避免在查看代码差异、打补丁、查看提交历史以及进行注释时产生问题。使用空格也使得代码对齐更轻松。

2.5. Keywords and True/False/Null

PHP 的 关键字 必须 使用小写形式。

PHP 的常量 true , false , 和 null 这三个 必须 使用小写形式。

3. Namespace and Use Declarations

namespace 声明之后 必须 存在一个空行。

所有的 use 声明 必须 位于 namespace 声明之后。

每条 use 声明 必须 只有一个 use 关键字。

use 语句块之后 必须 存在一个空行。

4. Classes, Properties, and Methods

此处的「类」泛指所有的「classes」、「Interfaces」以及「traits」。

4.1. 继承与实现

关键词 extendsimplements 必须 写在类名称的同一行。

类的开始花括号 必须 独占一行,结束花括号也 必须 在类主体后独占一行。

implements 的实现列表也 可以 分成多行,后续的每一行都缩进一次,这样做的话,每个实现接口名称都 必须 分开独立成行,包括第一个。

namespace Vendor\Package;

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

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // 类主体
}

4.2. 属性

每个属性都 必须 声明「访问控制符」。

一定不可 使用关键字 var 声明一个属性。

每条语句 一定不可 定义超过一个属性。

不该 使用下划线作为前缀,来区分访问控制属性 protectedprivate

4.3. 方法

所有的方法都 必须 声明「访问控制符」。

不该 使用下划线作为前缀,来区分访问控制属性 protectedprivate

方法名称后 一定不可 有空格,开始花括号 必须 独占一行,结束花括号也 必须 在方法主体后单独成一行。参数开始圆括号后和结束圆括号前 一定不可 有空格。

标准范例,注意其圆括号、逗号、空格及花括号的位置。

<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // 方法主体
    }
}

4.4. 方法的参数

参数列表中,每个逗号后面 必须 要有一个空格,而逗号前面 一定不可 有空格。

有默认值的参数,必须 放到参数列表的末尾。

参数列表 可以 分为多行,每个后续行缩进一次。这样,包括第一个参数在内的每一个参数都 必须 单独成行。

拆分成多行的参数列表后,结束圆括号以及方法的开始花括号 必须 写在同一行,中间用一个空格分隔。

<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // 方法主体
    }
}

4.5. abstract, final, and static

当需要声明 abstractfinal 时,必须 写在访问修饰符前,而 static必须 写在其后。

4.6. Methods and Function calls

方法及函数调用时,方法名或函数名与参数左圆括号之间 一定不可 有空格,参数右圆括号前也 一定不可 有空格。每个逗号前 一定不可 有空格,但其后 必须 有一个空格。

参数 可以 分列成多行,注意每个后续行要有一个缩进。如果这样,从第一个参数开始 必须 另起一行,并且每行 必须 只能有一个参数。

<?php
bar($arg, $arg2);

$foo->bar(
    $arg1,
    $arg2,
    $arg3
);

5. 控制结构(Control Structures)

控制结构的基本规范如下:

  • 控制结构关键词后 必须 有一个空格。
  • 左括号 ( 之后 与 右括号 ) 之前 一定不可 有空格。
  • 右括号 ) 与 开始花括号 { 之间 必须 有一个空格。
  • 结构体主体 必须 要有一次缩进。
  • 结束花括号 } 必须 在结构体主体后单独成行。

每个结构体的主体都 必须 被包含在成对的花括号中,让结构体更标准化,以及减少出错的可能性。

5.1. if, elseif, else

应该 使用关键词 elseif 代替所有 else if ,使得所有的控制关键字都像是单独的一个词。

注意以下范例中的空格、括号、花括号等等:

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

5.2. switch, case

标准的 switch 结构范例,留意括号、空格以及花括号的位置。

case 语句 必须 相对 switch 进行一次缩进,而 break 语句以及 case 内的其它语句都 必须 相对 case 进行一次缩进。

如果存在非空的 case 直穿语句,主体里 必须 有类似 // 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

直接范例:

<?php
while ($expr) {
    //结构体
}

do {
    //结构体
} while ($expr);

5.4. for

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

5.5. foreach

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

5.6. try, catch

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

6. 闭包(Closures)

闭包声明时,关键词 function 后以及关键词 use 的前后都 必须 要有一个空格。

开始花括号 必须 写在声明的同一行,结束花括号 必须 紧跟主体结束的下一行。

参数列表和变量列表的 左圆括号后 以及 右圆括号前,一定不可 有空格。

参数和变量列表中,逗号前 一定不可 有空格,而逗号后 必须 要有空格。

闭包中有默认值的参数 必须 放到列表的后面。

标准的闭包声明语句范例,注意其「括号」、「空格」以及「花括号」的位置。

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

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

参数列表以及变量列表 可以 分成多行,这样,包括第一个在内的每个参数或变量都 必须 单独成行,而列表的右圆括号与闭包的开始花括号 必须 放在同一行。

注意,闭包被直接用作函数或方法调用的参数时,以上规则仍然适用。

7. 总结

本指南故意删除了许多风格与实践, 它们包括但不限于:

  • 全局变量和常量的声明
  • 函数声明
  • 运算符与赋值
  • 行间对齐
  • 注释与文档描述块
  • 类名前缀与后缀
  • 最佳实践

本指南将来的修订和扩展 可能 会弥补上述或其他风格与最佳实践。

附录 A. 调查

A.1. 调查数据

A.2. Survey Legend

A.3. Survey Results


社区译注有一处错误本人已经提交,并且得到了社区的合并允许。

对于后面的附录,目前还没弄懂,感兴趣可以直接到原著中翻阅。

最后强调,代码规范的价值在于我们都遵循这个编码风格,而不是在于它本身。


参考文献

GitHub: https://github.com/php-fig/fig-standards

php-fig: https://www.php-fig.org/psr/

社区翻译: https://learnku.com/docs/psr

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342