PHP编码规范

 

  1. 0 前言

 

编码风格没有太多的好坏之分, 最重要的是风格保持一致,编码规范有助于规范我们编码的风格,使代码具有更好的可读性。编码风格百家齐放,不利于我们代码的维护和传承,根据大家平时的开发情况,制定了此PHP编码规范。

每项规范前面的(强制) 代表该规范需要强制执行, (建议)代表推荐执行但不强制。

注: 文中所有的变量名前面为了方便没有加”$”, 示意即可。

1 排版

1-1:(强制)程序块要采用缩进风格编写,缩进的空格数为4****个。

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

1-2****:(建议)关键字与其后的左括号之间有一个空格,而函数名与左括号之间不应有任何字符包括空格。

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

如:

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

1-3:(强制)开始的大括号位于一行的末尾,结束的括号位于最末一行后,且独占一行。

如:

if (a > b) {

}

1-4**(强制)if/while等结构体,即使只有一行,也必须加上左右花括号,不允许写成一行。**

说明: 这样做可读性更好,并且方便修改。

如:

if (a > b) {

a = 1;

}

 

1-5**(建议)适当控制每行代码的长度(一般不超过80个字符)**

说明: 代码更美观, 可读性更好

1-6**(强制)elseif语句使用elseif形式,不使用else if形式。**

说明: elseif 为标准语法

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

如:

funcA(a, b, c) {

}

1-8:(建议)避免由于对错误的条件做判断带来if的嵌套。

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

不推荐的方式:

if (a === false) {

// error handle

} else {

if (b === false) {

// handle

}

}

 

推荐的方式:

if (a === false) {

// error handle

}

if (b === false) {

// handle

}

 

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

说明: 这样做逻辑更一目了然。

if (a > b && c > d

&& e > f && h > j

&& z > x) {

}

1-10:(建议)多行的”=”可能的话尽量用空格对齐。

a     = 1;

ab   = 2;

abc = 3;

1-11: (强制)Switch语句中每个case的break必须和case间有4个空格的缩进。

case ‘A’:

a  = 2;

break;

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

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

$a = array(

‘a’ => ‘b’,

‘b’ => ‘c’,

‘c’ => ‘d’,

);

 

2 命名

2-1:(强制)全局变量以g_开头。

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

如:

g_count;

 

2-2**(强制)常量命名使用全部大写字符,单词之间以’_’连接。**

如:

PAGE_NUM

 

2-3**(强制)对于代码中的常量,必须用常量或define表示,不允许直接写在代码中。**

如:

define(‘PAGE_NUM’, 3);

 

2-4**(强制)关键字true、false、null必须小写**

2-5: (强制)私有函数命名需加上 ‘_’前缀。

private function _myPrivateFunc() {

}

 

2-6:  (强制)类method命名采用驼峰命名, 普通function采用过程函数风格命名。

如:

类method:

public function getName() {

}

普通function:

function show_me_the_money() {

}

 

2-7:  (强制)文件(除了类)命名使用小写字母,单词之间以’_’连接。

如:

show_lemma.php

 

2-8: (建议)配置文件的名称为配置文件名 + .conf.php, 不涉及类的都小写通过”_”连接。Yaf等框架要求的命名规范除外。

如:

good_version.conf.php

 

2-9:  (建议)类名应以大写字母开头,每个单词的首字母大写。

如:

ActionController

  1. 3 注释

  2. 3-1:(强制)文件、函数、类以及成员变量都必须包含注释。

  3. 类文件/普通文件的注释, 说明该文件的主要作用。

  4. 例:

  5. “A simple class describing employees” 说明类文件的主要作用。

  6. “@package Employee” 说明namespace(如果有)

  7. “@author George Schlossnagle” 说明作者信息

/**

  • A simple class describing employees

  • @package Employee

  • @author George Schlossnagle

*/

  1. 类注释, 说明类的主要工作。
  2. 例:
  3. “An example of documenting a class” 说明类的主要作用。
  4. “The employees annual salary” 说明变量的作用。
  5. “@var number” 说明变量的类型。
  6. “The class constructor” 说明方法的作用。
  7. “@param” 说明参数类型。
  8. “@access” 说明访问权限。
  9. “@return” 说明返回值。

/**

  • An example of documenting a class

*/

class Employee

{

/**

  • @var string

*/

var $name;

/**

  • The employees annual salary

  • @var number

*/

var $salary;

/**

  • @var number

*/

var $employee_id;

/**

  • The class constructor

  • @param number

*/

function Employee($employee_id = false) {

if ($employee_id) {

$this->employee_id = $employee_id;

$this->_fetchInfo();

}

}

/**

  • Fetches info for employee

  • @access 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

  • @returns number Monthly salary in dollars

*/

function monthlySalary() {

return $this->salary/12;

}

}

 

3-2: **(强制)不能使用#作为单行注释, 多行注释/* *   /不能出现在同一行。

 

3-3: (强制)函数必须通过param和return标记指明其参数和返回值。

 

3-4:  (建议)必要的地方使用非文档性注释,提高代码易读性。

 

注释规范遵守phpDocumentor注释规范, 更多请参见: http://manual.phpdoc.org/

4 编码原则

4-1:(强制)整形参数,需要用intval函数处理,注意intval返回有符号的数值,若数值过大,可以考虑使用floatval。

如:

intSalary = intval(salary);

4-2**(强制)对于函数返回值的判断,特别是true/false, 用===/!== 而不是==/!=。**

4-3: (强制)生成一个对象时,必须使用new Classname()的方式,不能用new Classname的方式。

4-4: (强制)所有的文件路径都需要利用框架提供的宏写成绝对路径。

4-5: (强制)对于长时间运行的脚本并且含有占用内存较大的变量,使用完后必须unset掉,避免内存占用过多。

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

4-7: (强制)除非特殊情况,否则不允许使用require和include,而使用对应的require_once/include_once。

4-8: (强制)预定义变量一律使用短格式,即:$_POST、$_GET、$_SERVER、$_ENV、$GLOBALS、$_COOKIE、$_SESSION、$_REQUEST、$_FILES等,不再使用长格式:$_HTTP_POST_VARS、$_HTTP_GET_VARS。

4-9: (建议)每个类单独为一个文件, 文件名为 原类名 + .class.php。文件中的类名由文件夹结构 + “_” + 原类名的形式组成。Yaf/Thinkphp等框架****要求的类和类文件命名规范除外。

说明: 利于管理,逻辑清楚,方便autoload等。

例如: 文件名: baidu/acl/Filter.class.php

原类名: Filter

文件中的class的名称: class Baidu_Acl_Filter

文件夹结构相当于package的名称,这样不会存在多产品命名冲突。

4-11:  (建议)尽量不要在php代码中出现html标签,将模板和代码分离。

4-12:   (建议)能用foreach的就不要用for,能用for的就不要用while。

说明: foreach比for容易理解,for比while容易理解。

4-13: (强制)前端访问必须有日志记录,记录条数应与访问一一对应。

4-14:(建议)数据库写操作必须有日志记录;记录条数应与操作一一对应。

4-15:(强制)对于文件更新操作,必须先写到一个临时文件中,然后用rename/mv操作。切忌直接在原文件上做更新。

4-16:(建议)字符串尽量用’ ‘而不是” “进行引用,一个是效率问题,一个是安全问题。

4-17: (强制)所有的define语句,常量必须用’’包括起来。

define(‘PAGE_NUM’, 3);

4-18: (强制)require后面需要带上括号。

require_once(“a.php”);

4-19: (强制)函数允许使用默认参数,但是默认参数需要放到参数列表最后面。

4-20: (强制)所有的全局变量应该写在函数的最开头,并且和后面的代码以空行隔开。

function a() {

global g_count;

global g_time;

a = 1;

}

 

**4-21: (强制)**在头文件中定义全局变量必须用$GLOBALS的形式,这样可以避免在函数中include导致的作用域问题。

  1. conf.php

 

5.安全编码

 

**5-1: (强制)所有的用户输入都是有害的,**对所有从客户端传入的数据都不信任, 需要做判断和过滤,否则可能会受到SQL Injection、XSS等攻击。

例如: $_GET, $_POST, $_COOKIE, $_FILES, $REQUEST等。

直接使用将可能存在被注入的危险。

 

5-2: (强制)用户的相关输入涉及数据库操作、文件操作等敏感操作时需要对输入做专门的转换。

例如: 数据库操作中数字型的需要做intval转换,字符串类型的需要通过mysql_real_escape_string过滤。

文件操作中类似 include_once(“$userInput”)等操作。

 

**5-3:  (强制)**用户上传的文件的文件名必须重新命名,并限制其后缀。

 

5-4:  (强制)将php配置中的 register_globals 设置为 Off。

register_globals允许php将$_GET,$_POST,$_COOKIE等变量里的内容自动注册为全局变量,如果程序里的某些变量没有经过初始化而直接使用将导致安全问题。

 

5-5: (强制)将php配置中的expose_php设置为Off。

避免PHP版本信息暴露。

5-6: (强制)php配置中error_reporting应该设置为输出 E_NOTICE级别的日志。

E_NOTICE级别的日志虽然算不上错误日志,但是却告诉了我们哪些地方存在安全隐患,例如:变量未初始化等等, 打开E_NOTICE有助于我们减少bug, 提前发现安全漏洞。