PHP代码规范

Author Avatar
Moon 5月 12, 2017

前言

  • 源码文件必须采用UTF-8编码,且不得有BOM头,某些历史遗留的GBK模块除外。
  • 编码风格没有太多的好坏之分, 最重要的是风格保持一致,编码规范有助于规范我们编码的风格,使代码具有更好的可读性。
  • PHP在新格尔内部应用得越来越广泛,但是却缺乏相应的编码规范支持,编码风格百家齐放,不利于我们代码的维护和传承, 根据大家平时的开发情况,制定了此PHP编码规范。
  • 每项规范前面的 [强制] 代表该规范需要强制执行, [建议] 代表推荐执行但不强制。
  • 注: 文中所有的变量名前面为了方便没有加”$”, 示意即可。
  • 本文档风格约定部分可能跟你的喜好有冲突,请尽量用包容的心态来阅读。有任何问题或建议,欢迎跟我们讨论: zhujian@cshen.cn

排版

[强制] [PHP002] 程序块要采用缩进风格编写,缩进的空格数建议为4个,单模块内必须统一。

解释
不同的缩进风格对代码的可读性影响很大,以tab为缩进单位在不同的tab step 下可读性也相差很多,所以将缩进定为一个soft tab即4个空格,这样在所有环境下缩进都会保持一致。


[建议] 关键字与其后的左括号之间有一个空格,而函数名与左括号之间不应有任何字符包括空格。

解释
虽然很多情况下编辑器的highlight已经做了区分,但是从格式上区分关键字和函数适用于所有的情况。

示例

1
2
关键字    if (a > b)
函数名 funcA()


[建议] 开始的大括号位于一行的末尾,结束的括号位于最末一行后,且独占一行。首括号也可另起一行,但一个模块内必须统一。

示例

1
2
3
if (a > b) {

}


[强制] [PHP003] if/while等结构体,即使只有一行,也必须加上花括号,不得写成一行。

解释
这样做可读性更好,并且方便修改。

示例

1
2
3
if (a > b) {
a = 1;
}


[建议] 一行代码不得超过120个字节,建议控制在80字节内;一个函数不得超过500行,建议控制在100行以内。

解释
代码更美观, 可读性更好


[建议] else-if语句使用else if形式,不使用elseif形式。


[建议] 函数名与其后的左括号之间不应有任何字符(包括空格) 函数调用的左括号与其第一个参数之间不应有任何字符(包括空格) 最后一个参数与右括号之间不应有任何字符(包括空格) 参数列表的逗号后面应有一个空格

示例

1
2
3
funcA(a, b, c) {

}


[建议] 避免由于对错误的条件做判断带来if的嵌套。

解释
减少if/else嵌套, 更利于代码逻辑的理解。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
不推荐的方式:
if (a === false) {
// error handle
} else {
if (b === false) {
// handle
}
}
推荐的方式:
if (a === false) {
// error handle
}

if (b === false) {
// handle
}


[建议] 如果过长的话需要另起一行。if 语句的条件若较多较长,应折行;新行以逻辑运算符起始,与第一行 if 左括号后的第一个字符对齐;折行后,每行条件具有独立而明确的语义

解释
这样做逻辑更一目了然。

示例

1
2
3
4
5
if (a > b && c > d
&& e > f && h > j
&& z > x) {

}


[建议] 多行的”=”可能的话尽量用空格对齐。

示例

1
2
3
a   = 1;
ab = 2;
abc = 3;


[强制] [PHP009] Switch语句中每个case的break必须和case间有缩进。

示例

1
2
3
case 'A':
a = 2;
break;


[强制] [PHP008] 初始化array如果采用多行结构时,数据项部分需要缩进,且最后一个数据项后面的逗号不可省略。

解释
这样做在修改代码增加数据项的时候不容易出现语法错误。

示例

1
2
3
4
5
$a = array(
'a' => 'b',
'b' => 'c',
'c' => 'd',
);


[建议] 复杂的表达式, 使用括号表明优先级, 而不完全依赖运算符优先级。

示例

1
2
3
4
5
6
7
// 不推荐方式:
if ($a && $b || $c + $b && $e) {
}

// 推荐方式:
if (($a && $b) || (($c + $b) && $e)) {
}


[建议] 同一个代码块的变量定义, 应该尽可能集中在块开始位置,提高可读性。


[建议] 除模板外,不允许使用 ?> 标记结尾, 避免其后误加的字符干扰页面渲染。


[建议] 产品线内必须统一换行符的使用, 推荐”\n”。


命名

[强制] [PHP025] 全局变量以g_开头。

解释
全局变量对代码影响很大,以g_开头便能在代码中一眼看出是全局变量。

示例

1
g_count;


[强制] [PHP004] 常量命名使用全部大写字符,单词之间以”_”连接。

示例

1
PAGE_NUM


[建议] 对于代码中的常量,建议用常量或define表示,不应直接写在代码中。

示例

1
define('PAGE_NUM', 3);


[强制] [PHP010] 关键字true、false、null必须小写


[强制] [PHP026] 类method命名采用驼峰命名, 普通function采用过程函数风格命名。

示例

1
2
3
4
5
6
7
类method:
public function getName() {
}

普通function
function show_me_the_money() {
}


[强制] 类成员变量和局部变量必须采用驼峰命名法,建议增加三字节的类型前缀:arr、str、int、bol、obj等

示例

1
$strName, $intAge


[建议] 文件(除了类)命名使用小写字母,单词之间以”_”连接。

示例

1
show_lemma.php


[建议] 配置文件的名称为配置文件名 + .conf.php, 不涉及类的都小写通过”_”连接。

示例

1
good_version.conf.php


[建议] 类名应以大写字母开头,每个单词的首字母大写。

示例

1
ActionController


[建议] final放在访问控制符的前面、访问控制符放在static的前面

示例

1
2
final public static function getInstance() {
}


注释

[建议] 文件、函数、类以及成员变量都应包含注释,关键代码必须有注释。
类文件/普通文件的注释, 说明该文件的主要作用。

示例
“A simple class describing employees” 说明类文件的主要作用。
“@package Employee” 说明namespace(如果有)
“@author George Schlossnagle” 说明作者信息

1
2
3
4
5
6
/**
* A simple class describing employees
*
* @package Employee
* @author George Schlossnagle
*/

类的注释, 说明该类的主要作用。

示例
“An example of documenting a class” 说明类的主要作用。
“The employees annual salary” 说明变量的作用。
“@var number” 说明变量的类型。
“The class constructor” 说明方法的作用。
“@param” 说明参数类型。
“@access” 说明访问权限。
“@return” 说明返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* An example of documenting a class
*/
class Employee
{
/**
* @var string
*/
private $name;

/**
* The employees annual salary
* @var number
*/
private $salary;

/**
* @var number
*/
private $employee_id;

/**
* The class constructor
* @param number
*/
public function Employee($employee_id = false) {
if ($employee_id) {
$this->employee_id = $employee_id;
$this->_fetchInfo();
}
}

/**
* Fetches info for employee
*
* @access private
*/
private function fetchInfo() {
$query = "SELECT name,
salary
FROM employees
WHERE employee_id = $this->employee_id";
$result = mysql_query($query);
list($this->name, $this->department_id) = mysql_fetch_row($result);
}

/**
* Returns the monthly salary for the employee
* @return number Monthly salary in dollars
*/
public function monthlySalary() {
return $this->salary/12;
}
}

[强制] [PHP027] 不能使用#作为单行注释, 多行注释/ * **/不能出现在同一行。


[强制] [PHP028] 函数必须通过param和return标记指明其参数和返回值。


[建议] 注释需要遵守phpDocumentor等注释规范,同一团队内部必须保持一致。


[建议] 必要的地方使用非文档性注释,提高代码易读性。

编码原则

[建议]对传入或返回的参数进行类型检查和显式转换。

示例

1
$intSalary = (int) $salary;


[强制] 对于函数返回值的判断,特别是true/false, 必须用===或!==。


[强制] [PHP029] 生成对象时,必须使用new Classname(),不能用new Classname。


[强制] 所有文件路径都需要利用框架提供的宏写成绝对路径。


[建议] 对于长时间运行的CLI程序,需要及时unset无用变量,尤其是PHP5.2上。


[强制] 对于一些系统操作,使用php内置的函数例如rename、touch等即可。尽量避免使用exec调用shell命令。


[建议] 除非特殊情况,否则不允许使用require和include,而使用对应的require_once/include_once。


[建议] 配置项与PHP代码分离,不随CVS/SVN发布


[强制] 预定义变量一律使用短格式,即:$_POST、$_GET、$_SERVER、$_ENV等,不再使用长格式:$_HTTP_POST_VARS、$_HTTP_GET_VARS。


[强制] 类文件名必须符合所用框架自动加载规范,常见的是PSR-0。


[建议] 除模板外,尽量不要在php代码中出现html标签。


[建议] 能用foreach的就不要用for,能用for的就不要用while。


[强制] 每个前端访问请求必须有且仅有一条notice日志。


[建议] 数据库写操作必须有日志记录;记录条数应与操作一一对应。


[强制] 文件更新操作,必须使用临时文件+mv的方式,切忌直接写在原文件。


[建议] 字符串尽量用’ ‘而不是” “进行引用,一个是效率问题,一个是安全问题。


[强制] [PHP031] 所有的define语句,常量必须用’’包括起来。

示例

1
define('PAGE_NUM', 3);


[建议] require/include后面不使用括号。

示例

1
require_once "a.php";


[强制] [PHP020] 函数允许使用默认参数,但是默认参数需要放到参数列表最后面。


[强制] [PHP032] 所有的全局变量应该写在函数的最开头,并且和后面的代码以空行隔开。

示例

1
2
3
4
5
6
function a() {
global g_count;
global g_time;

a = 1;
}


[强制] [PHP033] 禁止使用and, or, 而是使用&&, ||


[建议] 避免使用$i, $j这样无意义的变量名, 除非是用作循环计数变量。


[建议] 避免使用php逻辑代码作为配置, 以降低改配置的危险性。


[建议] 进行==判断时,建议把常量放在前面, 避免误写成赋值操作。

示例

1
2
3
4
5
6
7
不推荐形式:
if ($a == 1) {
}

推荐形式:
if (1 == $a) {
}


[建议] 使用变量前赋初值,提高可读性,也可避免误用别处定义的同名变量。


[建议] 错误码使用统一文件集中配置,并且使用常量,而不应裸写数字


[建议] 对于无需子类化的实体类以及不应重载的方法使用final关键字限定。


[强制] 对于不应实例化的父类使用abstract关键字限定。


[建议] 避免重载父类的static成员,这在5.2.x存在问题。


[建议] 对于仅用于某个函数或类的全局变量,使用static的局部变量或者类成员变量代替。


[建议] 在头文件中用$GLOBALS定义全局变量,避免局部包含导致的作用域问题。

代码性能

[强制] [PHP034] 把重复调用放在循环体外。

示例

1
2
3
4
5
6
不推荐形式:
for ($i = 0; $i < count($arr); $i++)

推荐形式:
$arrCount = count($arr);
for ($i = 0; $i < $arrCount; $i++)