为了尽可能的提升阅读其他人代码时的效率,下面例举了一系列的通用规则,特别是有关于PHP代码风格的。各个成员项目间的共性组成了这组代码规范。当开发者们在多个项目中合作时,本指南将会成为所有这些项目中共用的一组代码规范。 因此,本指南的益处不在于这些规则本身,而在于在所有项目中共用这些规则。

1. 概述

  • 代码必须遵守 PSR-1。

  • 代码必须使用4个空格来进行缩进,而不是用制表符。

  • 一行代码的长度不建议有硬限制;软限制必须为120个字符,建议每行代码80个字符或者更少。

  • 命名空间(namespace)的声明下面必须有一行空行,并且在导入(use)的声明下面也必须有一行空行。

  • 类(class)的左花括号必须放到其声明下面自成一行,右花括号则必须放到类主体下面自成一行。

  • 方法(method)的左花括号必须放到其声明下面自成一行,右花括号则必须放到方法主体的下一行。

  • 所有的属性(property)方法(method) 必须有可见性声明;抽象(abstract)终结(final)声明必须在可见性声明之前;而静态(static)声明必须在可见性声明之后。

  • 在控制结构关键字的后面必须有一个空格;而方法(method)函数(function)的关键字的后面不可有空格。

  • 控制结构的左花括号必须跟其放在同一行,右花括号必须放在该控制结构代码主体的下一行。

  • 控制结构的左括号之后不可有空格,右括号之前也不可有空格。

1.1. 示例

这个示例中简单展示了上文中提到的一些规则:

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()
{
// 方法主体
}
}

2. 通则

2.1 基础代码规范

代码必须遵守 PSR-1 中的所有规则。

2.2 源文件

所有的PHP源文件必须使用Unix LF(换行)作为行结束符。

所有PHP源文件必须以一个空行结束。

纯PHP代码源文件的关闭标签?> 必须省略。

2.3. 行

行长度不可有硬限制。

行长度的软限制必须是120个字符;对于软限制,代码风格检查器必须警告但不可报错。

一行代码的长度不建议超过80个字符;较长的行建议拆分成多个不超过80个字符的子行。

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

空行可以用来增强可读性和区分相关代码块。

一行不可多于一个语句。

2.4. 缩进

代码必须使用4个空格,且不可使用制表符来作为缩进。

注意:代码中只使用空格,且不和制表符混合使用,将会对避免代码差异,补丁,历史和注解中的一些问题有帮助。空格的使用还可以使通过调整细微的缩进来改进行间对齐变得更加的简单。

2.5. 关键字和 True/False/Null

PHP关键字(keywords)必须使用小写字母。

PHP常量truefalsenull 必须使用小写字母。

3. 命名空间(Namespace)导入(Use)声明

命名空间(namespace)的声明后面必须有一行空行。

所有的导入(use)声明必须放在命名空间(namespace)声明的下面。

一句声明中,必须只有一个导入(use)关键字。

导入(use)声明代码块后面必须有一行空行。

示例:

namespace Vendor\Package;

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

// ... 其它PHP代码 ...

4. 类(class)属性(property)方法(method)

术语“类”指所有的类(class)接口(interface)特性(trait)

4.1. 扩展(extend)实现(implement)

一个类的扩展(extend)实现(implement)关键词必须类名(class name)在同一行。

类(class)的左花括号必须放在下面自成一行;右花括号必须放在类(class)主体的后面自成一行。

namespace Vendor\Package;

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

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
// 常量、属性、方法
}

实现(implement)列表可以被拆分为多个缩进了一次的子行。如果要拆成多个子行,列表的第一项必须要放在下一行,并且每行必须只有一个接口(interface)

namespace Vendor\Package;

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

class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// 常量、属性、方法
}

4.2. 属性(property)

所有的属性(property)必须声明其可见性。

变量(var)关键字不可用来声明一个属性(property)

一条语句不可声明多个属性(property)

属性名(property name) 不推荐用单个下划线作为前缀来表明其保护(protected)私有(private)的可见性。

一个属性(property)声明看起来应该像下面这样。

namespace Vendor\Package;

class ClassName
{
public $foo = null;
}

4.3. 方法(method)

所有的方法(method)必须声明其可见性。

方法名(method name) 不推荐用单个下划线作为前缀来表明其保护(protected)私有(private)的可见性。

方法名(method name)在其声明后面不可有空格跟随。其左花括号必须放在下面自成一行,且右花括号必须放在方法主体的下面自成一行。左括号后面不可有空格,且右括号前面也不可有空格。

一个方法(method)声明看来应该像下面这样。 注意括号,逗号,空格和花括号的位置:

namespace Vendor\Package;

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

4.4. 方法(method)的参数

在参数列表中,逗号之前不可有空格,而逗号之后则必须要有一个空格。

方法(method)中有默认值的参数必须放在参数列表的最后面。

namespace Vendor\Package;

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

参数列表可以被拆分为多个缩进了一次的子行。如果要拆分成多个子行,参数列表的第一项必须放在下一行,并且每行必须只有一个参数。

当参数列表被拆分成多个子行,右括号和左花括号之间必须又一个空格并且自成一行。

namespace Vendor\Package;

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

4.5. 抽象(abstract)终结(final)和 静态(static)

当用到抽象(abstract)终结(final)来做类声明时,它们必须放在可见性声明的前面。

而当用到静态(static)来做类声明时,则必须放在可见性声明的后面。

namespace Vendor\Package;

abstract class ClassName
{
protected static $foo;

abstract protected function zim();

final public static function bar()
{
// 方法主体部分
}
}

4.6. 调用方法和函数

调用一个方法或函数时,在方法名或者函数名和左括号之间不可有空格,左括号之后不可有空格,右括号之前也不可有空格。参数列表中,逗号之前不可有空格,逗号之后则必须有一个空格。

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

参数列表可以被拆分成多个缩进了一次的子行。如果拆分成子行,列表中的第一项必须放在下一行,并且每一行必须只能有一个参数。

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

5. 控制结构

下面是对于控制结构代码风格的概括:

  • 控制结构的关键词之后必须有一个空格。

  • 控制结构的左括号之后不可有空格。

  • 控制结构的右括号之前不可有空格。

  • 控制结构的右括号和左花括号之间必须有一个空格。

  • 控制结构的代码主体必须进行一次缩进。

  • 控制结构的右花括号必须主体的下一行。

每个控制结构的代码主体必须被括在花括号里。这样可是使代码看上去更加标准化,并且加入新代码的时候还可以因此而减少引入错误的可能性。

5.1. ifelseifelse

下面是一个if条件控制结构的示例,注意其中括号,空格和花括号的位置。同时注意elseelseif要和前一个条件控制结构的右花括号在同一行。

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

推荐elseif来替代else if,以保持所有的条件控制关键字看起来像是一个单词。

5.2. switchcase

下面是一个switch条件控制结构的示例,注意其中括号,空格和花括号的位置。case语句必须要缩进一级,而break关键字(或其他中止关键字)必须case结构的代码主体在同一个缩进层级。如果一个有主体代码的case结构故意的继续向下执行则必须要有一个类似于// no break的注释。

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. whiledo while

下面是一个while循环控制结构的示例,注意其中括号,空格和花括号的位置。

while ($expr) {
// structure body
}

下面是一个do while循环控制结构的示例,注意其中括号,空格和花括号的位置。

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

5.4. for

下面是一个for循环控制结构的示例,注意其中括号,空格和花括号的位置。

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

5.5. foreach

下面是一个foreach循环控制结构的示例,注意其中括号,空格和花括号的位置。

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

5.6. trycatch

下面是一个try catch异常处理控制结构的示例,注意其中括号,空格和花括号的位置。

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

6. 闭包

声明闭包时所用的function关键字之后必须要有一个空格,而use关键字的前后都要有一个空格。

闭包的左花括号必须跟其在同一行,而右花括号必须在闭包主体的下一行。

闭包的参数列表和变量列表的左括号后面不可有空格,右括号的前面也不可有空格。

闭包的参数列表和变量列表中逗号前面不可有空格,而逗号后面则必须有空格。

闭包的参数列表中带默认值的参数必须放在参数列表的结尾部分。

下面是一个闭包的示例。注意括号,空格和花括号的位置。

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

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

参数列表和变量列表可以被拆分成多个缩进了一级的子行。如果要拆分成多个子行,列表中的第一项必须放在下一行,并且每一行必须只放一个参数或变量。

当列表(不管是参数还是变量)最终被拆分成多个子行,右括号和左花括号之间必须要有一个空格并且自成一行。

下面是一个参数列表和变量列表被拆分成多个子行的示例。

$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
};

把闭包作为一个参数在函数或者方法中调用时,依然要遵守上述规则。

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

7. 结论

本指南有意的省略了许多元素的代码风格。主要包括:

  • 全局变量和全局常量的声明

  • 函数声明

  • 操作符和赋值

  • 行间对齐

  • 注释和文档块

  • 类名的前缀和后缀

  • 最佳实践

以后的代码规范中可能会修正或扩展本指南中规定的代码风格。

PHP规范PSR2的更多相关文章

  1. PHP编码规范PSR-2

    .note-content { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeit ...

  2. PHP中PSR-[0-4]代码规范

    PHP-FIG 在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:www.php-fig.org.就是这个联盟组织发明和创造了PSR-[0-4] ...

  3. PSR : php编码规范

    诸王混战 关于开发标准这块,可以说一直都是风格迥异,各家都有各家的玩法,民间更是个人玩个人的.目前我们国内比较出名的几个框架(Yii,Laravel) 都已经支持Composer并且加入了PHP-FI ...

  4. 【PSR规范专题(1)】PSR-0+namespace+spl_autoload_register实现框架模型

    了解命名空间 namespace是PHP5.3版本加入的新特性,用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题: 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/ ...

  5. php规范

    PSR-0 自动加载 PSR-1 基本代码规范 PSR-2 代码样式 PSR-3 日志接口

  6. PSR-4——新鲜出炉的PHP规范

    FIG 制定的PHP规范,简称PSR,是PHP开发的事实标准. PSR原本有四个规范,分别是: PSR-0 自动加载 PSR-1 基本代码规范 PSR-2 代码样式 PSR-3 日志接口 2013年底 ...

  7. php设计模式--面向对象编程规范PSR

    php业界提出大家要遵循的面向对象编码规范,下面一一列出. PSR-0: 1.命名空间必须与绝对路径一致 2.类的首字母必须大写 3.出入口文件外,其他‘.php’必须只有一个类 PSR-1:基础编码 ...

  8. PSR-PHP开发规范(本文版权归作者:luluyrt@163.com)

    遵循PSR-4的自动加载 一.简介 首先这里要了解PSR,Proposing a Standards Recommendation(提出标准建议)的缩写,就是一种PHP开发规范,让我们研发出来的代码更 ...

  9. [转载]PHP中PSR-[0-4]规范

      PHP是世界上最伟大的语言,这一点是毋庸置疑的吧.哈哈哈哈哈哈 .这个霸气的开头不错!(^__^) 但是正是因为伟大,所以用的人也就多了,人一多,再牛逼再伟大的东西,都会产生问题,逐渐就造成了很多 ...

随机推荐

  1. 免安裝、免設定的 Hadoop 開發環境 - cloudera 的 QuickStart VM

    cloudera 的 QuickStart VM,為一種免安裝.免設定 Linux 及 Hadoop,已幫你建好 CDH 5.x.Hadoop.Eclipse 的一個虛擬機環境.下載後解壓縮,可直接以 ...

  2. Html5 绘制五星红旗

    Html5+JavaScript 在Canvas上绘制五星红旗,具体思路如下图所示: 绘制思路在上图中已有说明,具体代码如下: <script type="text/javascrip ...

  3. Atitit图像处理的用途

    Atitit图像处理的用途 1.1. 分类识别 (人脸检测,肤色识别,人类检测:1 1.2. 炫丽的动态按钮生成:色相旋转+自己的草书等图片合成,图片自动裁剪1 1.3. 集成调用自绘gui接口:识别 ...

  4. iOS --------Crash 分析(一)

    iOS Crash 分析(文一)- 开始 1. 名词解释 1. UUID 一个字符串,在iOS上每个可执行文件或库文件都包含至少一个UUID.目的是为了唯一识别这个文件. 2. dwarfdump 苹 ...

  5. Knockout中文开发指南(完整版API中文文档) 目录索引

    a, .tree li > span { padding: 4pt; border-radius: 4px; } .tree li a { color:#46cfb0; text-decorat ...

  6. 如何转型成为SQL Server DBA

        本篇PPT是我在2015 MVP OPEN Day Comunity Camp上分享的课程.之所以选择这个主题是因为有很多人曾经问过这方面的问题,而与之相关的主题却少之又少,因此我希望将自己的 ...

  7. 【转】WPF防止界面卡死并显示加载中效果

    原文地址:http://www.cnblogs.com/linyijia/archive/2013/02/06/2900609.html <Window x:Class="Loadin ...

  8. Unity3D知识框架

    美术部分:           3d模型,材质,纹理,shader,Animator,Animation,天空盒,灯光效果,烘焙 程序部分:           基本组成:               ...

  9. 创建 floating IP - 每天5分钟玩转 OpenStack(106)

    先复习一下前面我们讨论的知识. 当租户网络连接到 Neutron router,通常将 router 作为默认网关.当 router 接收到 instance 的数据包,并将其转发到外网时: 1. r ...

  10. flat network 原理与配置 - 每天5分钟玩转 OpenStack(86)

    flat network 是不带 tag 的网络,要求宿主机的物理网卡直接与 linux bridge 连接,这意味着: 每个 flat network 都会独占一个物理网卡. 上图中 eth1 桥接 ...