PHP编码规范-笔记
所有的代码都要变成可供他人容易阅读的
良好的代码书写习惯 + 良好的注释习惯 + PhpDocumentor = 程序说明书
整理日期:2013-07-30
为什么要编码规范:
编码规范(code conventions)对于程序员而言尤为重要,有以下几个原因:
1.在一个软件的生命周期中,80%的花费用于维护。
2.几乎没有任何一个软件在其整个生命周期中均由最初的开发人员来维护。
3.编码规范可以改善软件的可读性,可以让程序员尽快而彻底地理解新的代码。
规范不是真理,它无关对错与是非,它影响的是您的习惯。您不遵循规范,您的代码依旧可以正常运行,但您不是一个人在战斗。因此,我们还是希望您能严格遵循此规范。另外,没有一成不变的规则,也有很多规则没有定义到的地方,如果您对本规范有何意见或建议,请您反馈过来,我们会“谨慎修改,严格执行”。
第1章 排版规则
1.1 缩进规范
所有的缩进使用空格取代Tab制表符。缩进的单位为 4 个空格。
说明: 以免用不同的编辑器阅读程序时,因 Tab 键所设置的空格数目不同而造成程序布局变化。虽然使用空格会增加文件的大小,但在局域网中几乎可以忽略,且在编译过程中也可被消除掉。
1.2 大括号规范
(1) 程序块的分界符大括号'{'和'}',应各独占一行并且位于同一列,同时与引用它们的语句左对齐。
(2) 在函数体的定义,类的定义,以及if、for、do、while、switch、case语句中的左大括号'{'应放在行尾,与右括号')'之间用一个空格隔开。 右大括号'}'应与左大括号'{'所在行的行首处在同一列。比如:
function outer($a, $b) { for ( $i = 0; $i < 10; $i++ ) { $a += $b; } return $a; }
(3) if、for、do、while等语句的执行语句部分无论多少都要加括号{}。比如:
if ( true == $a ) { return; }
1.3 空格规范
(1) 括号内侧(左括号后面,右括号前面)不应有空格。比如:
intval($a); $b[0];
(2) 语法关键字(if, for , while, switch 等)后必须加空格。比如:
if ($count > 100) { // program code }
(3) 函数名与左括号之间不应该有空格,这能帮助区分关键字和函数调用。比如:
$a = intval($a); if ($a) { //code }
(4) 所有的二元操作符(+, -, *, /, =, >, <, ==, &&, ||等等)应用空格将其与操作数隔开。比如:
$a + $b; //算术运算符 $a = $b; //赋值运算符 $a > $b; //比较运算符 $a && $b; //逻辑运算符
(5) 一元操作符(++, --, !)与其操作数之间不应有空格,除非操作符是个单词,比如typeof。比如:
$a++; --$a; !$a;
(6) 每个逗号','后应跟一个空格。比如:
get_db_info($host, $user, $passwd);
(7) 每个控制部分(比如for语句)中的分号';'后须跟一个空格。比如:
for ( $i = 0; $i < 10; $i++ ) { //code }
(8) 字符串连接符'.'前后都加空格。比如:
$my_name = 'file_' . $var1;
(9) 匿名函数在function和左括号'('之间应有一个空格。
$a = function ($e) { return $e; };
(10) 右花括号'}'后紧接有内容,括号后要加空格。比如:
if ( $a > $b ) { //code } else { //code }
1.5 换行规范
(1) if、for、do、while、case、switch、default等语句自占一行。比如:
if ( NULL == $user ) { //code }
(2) 较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。比如:
if ((taskno < max_act_task_number) && (stat_stat_item_valid(stat_item))) { // program code }
for (i = 0, j = 0; (i < first_word_length) && (j < second_word_length); i++, j++) { // program code }
1.6 空行规范
谁也不愿意看到挤在一堆的无序的代码。我们在写代码的时候总是会利用一些空行来增加代码可读性。合理的利用空格来区分代码段会使代码的逻辑思路更加明确。我们强行规定的空行有以下情况:
(1) <?php 之后必须有且只有1个空行
(2) 两个函数之间必须有1个空行。
(3) return、die、exit之前如果有其他语句的情况下应加上一个空行。
(4) 相对独立的程序块之间、变量说明之后必须加空行。
第2章 命名规范
2.1 命名方式
规范使用三种书写方式:
(1) Pascal 命名规则
将标识符的每个单词的首字母都大写。
例如:BackColor
(2) Camel 命名规则
标识符的首字母小写,而后面连接的单词的首字母都大写。
例如:backColor
(3) Linux C命名规则
变量所有字母都使用小写,使用'_'作为每个词的分界。
变量名必须有一定的意义,并且意义准确。禁止拼音命名法。
例如:有一个变量用于保存图书的数目,可以命名为number_of_book或者num_of_book。不建议使用i,j,n等,因为它没有意义。也不建议使用 number或book,因为意义不准确。
2.2 局部变量
所有变量都要预先声明,并注明其意义,在函数的首部定义所有的变量。不要使用一个声明一个。尽量减少全局变量的使用。不要让局部变量覆盖全局变量。
变量所有字母都使用小写,使用'_'作为每个词的分界。变量名字应该使用名词或者形容词+名词的方式。如$value,$new_value。
例如:
function handleError($errorNumber) { $error = osErr($errorNumber); $time_of_error = osErr->GetTimeOfError(); $error_processor = osErr->GetErrorProcessor(); }
2.3 全局变量命名
全局变量使用 g_ 前缀。
例如:
global $g_Log;
2.4 静态变量命名
静态变量使用 s_ 前缀,如: $s_value。
2.5 临时变量命名
不要将在循环中频繁使用的临时变量如$i,$j等用于其它用途。
2.6 方法/函数中参数命名
参数的名字使用 Camel 命名方法。
2.7 全局常量
全局常量全部大写,用'_'分隔每个单词。
理由:
这是命名全局常量的传统。您要注意不要与其它的定义相冲突。
例如:
define('A_GLOBAL_CONSTANT', 'Hello world!');
2.8 类命名
用 Pascal 命名规则(首字母大写),尽量谨慎的使用缩写,不要用下划线作类名单词连接符。
在类中,属性定义在前边,公用方法放到专用方法前边。
对于派生类的命名应该避免带其父类名的诱惑,一个类的名字只与它自身有关,和它的父类叫什么无关。
一个类对应到一个文件。存放类的文件采用 ClassName.class.php 方式命名。
2.9 类属性命名
类中的属性使用Camel 命名法。
2.10 类方法命名
类中的方法使用Camel命名法,命名建议使用动宾结构(动词+名词,如addUser)或系表结构(如isLocked)的方式。
2.11 函数命名
函数名字采用 C GNU 的惯例,所有的字母使用小写字母,使用'_'分割单词。
理由:
这样容易与类方法区分开。
例如:
function some_body_function() { }
2.12 私有属性与私有方法命名
以 _ 开头,如
private $_privateValue; private static $_sPrivateStaticValue; private function _initialize() { // program code };
2.13 缩写词不要全部使用大写字母
无论如何,当遇到以下情况,您可以用首字母大写其余字母小写来代替全部使用大写字母的方法来表示缩写词。
使用: getHtmlStatistic.
不使用: getHTMLStatistic.
部分约定俗成的缩写除外,比如PDO 类库本身全大写,那么 class MyPDO extends PDO{}是合理的。
第3章 编程规范
3.1 数组的定义
(1) 关联数组定义和使用时中 key 值前后必须加单引号,并且每个元素占一行。比如:
array( 'name' => 'd5s.cn', 'gender' => 'php' );
(2) 索引数组定义所有元素位于同一行。比如,
array('a', 'b', 'c');
3.2 引号的使用
(1) 引号统一使用'单引号,只有当引号重叠时才使用"双引号,这样每进程可以节省几百 K 内存。
(2) 使用"号自动转义变量时必须在变量前后加"{}"。比如,
$str = "Marry is {$age}";
3.3 if 语句
虽然在 PHP 中else if 和 elseif 的作用基本上是一样的。但是为了代码的统一性(也有传言 else if 会出现不稳定的情况),我们要求将 elseif 之间不保留空格。if语句应如以下格式:
if (condition) { //statements; } elseif (condition) { //statements; } else { //statements; }
3.4 避免嵌入式的赋值
比如,避免这样书写
$d = ($a = $b + $c) + $r;
3.5 避免没有含义的数字
一个在源代码中使用了的赤裸裸的数字,包括作者,在三个月后,没人会知道它的含义。
使用 define()来给您想表示某样东西的数值一个真正的名字,而不是采用赤裸裸的数字,例如:
define("PRESIDENT_WENT_CRAZY", "22"); define("WE_GOOFED", "19"); define("THEY_DIDNT_PAY", "16");
if (PRESIDENT_WENT_CRAZY == $foo) { start_thermo_nuclear_war(); } elseif (WE_GOOFED == $foo) { refund_lotso_money(); } elseif (THEY_DIDNT_PAY == $foo) { infinite_loop(); } else { happy_days_i_know_why_im_here(); }
3.6 总是将恒量放在等号的左边
主要原因是假如您在等式中漏了一个等号,语法检查器会为您报错。比如:
if (6 == $errorNum) { //code }
3.7 return 语句
一条有返回值的return语句不要使用括号'()'来括住返回值。
3.8 循环计数器
允许使用一个单字符变量名的唯一情形是当它作为一个循环计数器的时候。在这种情况下,外层循环的计数器应当始终是 $i。如果有一个循环处于这个循环的内部,它的计数器应当是 $j,进而是 $k,等等。如果循环的计数器是一个已经存在并且名字有意义的变量,本规范并不适用。例如:
for ($i = 0; $i < $outer_size; $i++) { for ($j = 0; $j < $inner_size; $j++) { foo($i, $j); } }
3.9 SQL规则
(1) 在 PHP 中嵌入的 SQL 语句关键字全部采用大写;
(2) 表名和字段名要用反引号(`)引起来以防止因为字段名中包含空格而出现错误;
(3) 数据值两边用单引号包括('),并且应确保数据值中的单引号已经转义以防止 SQL 注入;
(4) 能使用多表查询一次查询的数据要一次读完,避免多次查询数据库。
比如:
$sql = "SELECT `user`.`name` FROM `user` WHERE `id` = '{$id}' LIMIT 1";
3.10 三元运算符
三元运算符,在一行代码里只允许使用一级。三元运算符只应该用来做简单的事情。它们只适合拿来做赋值用,根本不是用来做函数调用或者任何复杂的事情的。
示例:不应该使用它们的地方 (($i < $size) && ($j > $size)) ? do_stuff($foo) : do_stuff($bar); 示例:使用它们的合适地方 $min = ($i < $j) ? $i : $j;
3.11 初始化变量
变量使用前应初始化,使用未初始化变量将报E_NOTICE错误。这些错误可以通过使用内嵌的 isset() 或者empty()函数检查一个变量是否被设置来避免。
示例: 老办法 if ($forum) … 新办法: if (!empty($forum)) … if (isset($forum)) …
3.12 输入变量的初始化
无论是函数的参数还是通过URL传递的变量,在调用之前均必须对其进行预处理以及设定默认值。
字符串必须进行trim及转义的处理,并且如果变量的值是在我们预计的范围之内,需要对变量的非法值做出相应的处理;对于数字型的变量则需要进行intval或者floatval的处理。
3.13 其他杂项
(1) 纯PHP文件去掉底部的"?>"。
(2) 所有PHP、HTML文件均保存为No Bom UTF-8的字符编码。
(3) 不允许把多个短语句写在一行中,即一行只写一条语句。
(4) 一个函数仅完成一件功能,不要设计多用途面面俱到的函数。
第4章 注释规则
4.1 函数头部注释
每个函数之前应当有注释,告诉一个程序员使用这个函数所需要知道的事情。注释应该确保其他人不必察看这个函数的代码,就可以自信地在自己的代码中调用这个函数。注释包括的信息:
/** * 函数的含义说明 * @param mixed $arg1 参数一的说明 * @param mixed $arg2 参数二的说明 * @access public * @return bool 返回值说明 * @author 作者 */
4.2 删除废除的注释
废除的注释,注释的代码要及时删除。
4.3 常量加注释
对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量的注释应放在其上方相邻位置或右方。示例:
// active statistic task number define('MAX_ACT_TASK_NUMBER', 1000);
define('MAX_ACT_TASK_NUMBER', 1000); // active statistic task number
4.4 数据结构声明加注释
数据结构声明(数组),必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。
示例:
// sccp interface with sccp user primitive message name $sccp_user_primitive = array( 'N_UNITDATA_IND' => 1, // sccp notify sccp user unit data come 'N_NOTICE_IND' => 2, // sccp notify user the No.7 'N_UNITDATA_REQ' => 3 // sccp user's unit data );
4.5 全局变量注释
全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。
4.6 注释缩排
注释与所描述内容进行同样的缩排,可使程序排版整齐,并方便注释的阅读与理解。如:
function example_fun() { //fdgfd CodeBlock One // code two comments CodeBlock Two }
4.7 将注释与其上面的代码用空行隔开。如:
// code one comments program code one // code two comments program code two
4.8 连续case注释
对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。这样比较清楚程序编写者的意图,有效防止无故遗漏break语句。示例:
switch ($i) { case 'CMD_INIT': echo 'i equals 0'; break; case 'CMD_START': echo 'i equals 1'; // now jump into case CMD_A case 'CMB_A': echo 'i equals 2'; break; }
4.9 注释格式
注释格式统一,单行注释必须使用//,多行使用一对/*…*/
4.10 注释以中文为主
注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。
4.11 记录所有的空语句
总是记录下for或者是while的空块语句,以便清楚的知道该段代码是漏掉了,还是故意不写的。
for ( $i = 0; $i < 100; $i++ ) { // 空循环 }