• 展开微博窗口
  • QQ:826945906
  • 微信:u200714928
  • 展开分类目录
胡伟

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 注释

 

  1. 3-1:(强制)文件、函数、类以及成员变量都必须包含注释。
  2.       类文件/普通文件的注释, 说明该文件的主要作用。
  3.       例:
  4.           “A simple class describing employees” 说明类文件的主要作用。
  5.           “@package Employee” 说明namespace(如果有)
  6.           “@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导致的作用域问题。

   

<?php

function func() {

   require_once(‘a.conf.php’);

   // do something

}

func();

require_once(‘a.conf.php’);

echo “bad: $g_bad\ngood: $g_good\n”;

?>

  1. conf.php

<?php

// bad

$g_bad = ‘bad’;

// good

$GLOBALS[‘g_good’] = ‘good’;

?>

 

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, 提前发现安全漏洞。

码字很辛苦,转载请注明来自胡伟的博客《PHP编码规范》

评论