- 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
3 注释
3-1:(强制)文件、函数、类以及成员变量都必须包含注释。
类文件/普通文件的注释, 说明该文件的主要作用。
例:
“A simple class describing employees” 说明类文件的主要作用。
“@package Employee” 说明namespace(如果有)
“@author George Schlossnagle” 说明作者信息
/**
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” 说明返回值。
/**
- 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导致的作用域问题。
- 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, 提前发现安全漏洞。