PHP编码规范与原则

本条规范同样适用于 PHP、HTML、CSS、JavaScript。

前言

有太多的PHP程序猿都比较个性,对于编程也有自己的风格和习惯。暂且不说每个程序猿的习惯或风格是否合理,有自己的个性无可厚非,如果是单打独斗独立承担项目开发任务的话那也没什么,但是如果是团队合作开发的话,每个人都有自己的独立个性的编码习惯那就乱套了,别人无法清楚的读懂你的代码,同时你也无法很轻松的阅读别人的代码,互相抵触的情绪难免。本规范由编程原则组成,融合并提炼了开发人员长时间积累下来的成熟经验,意在帮助开发者养成良好一致的编程风格。

标准化的重要性和好处

    当一个软件项目尝试着遵守公共一致的标准时,可以使参与项目的开发人员更容易了解项目中的代码、弄清程序的状况。使新的参与者可以很快的适应环境,防止部分参与者出于节省时间的需要,自创一套风格并养成终生的习惯,导致其他人在阅读时浪费过多的时间和精力。而且在一致的环境下,也可以减少编码出错的机会。标准不是项目成功的关键,但可以帮助我们在团队协作中有更高的效率并且更加顺利的完成既定的任务。

PHP编码规范与原则

文件编码及编辑器格式

编码

请调整您的编辑器文件编码为 UTF-8,并关闭 UTF-8 BOM的功能。切记请不要使用windows自带的记事本编辑项目文件。

注意:请确认你的编辑器不会有意或无意的保存文件为 UTF-8 BOM 格式, 否则可能造成系统通信不正常。

缩进

每个缩进的单位约定是一个Tab(禁止设置为空格替代,Tab宽度应表示为4个空白字符宽度),需每个参与项目的开发人员在编辑器(UltraEdit、EditPlus、Zend Studio等)中进行强制设定,以防在编写代码时遗忘而造成格式上的不规范。

换行

PHP项目中使用Unix风格的换行符,即只有换行( LF 或 “\n” )没有回车( CR 或 “\r” ),请在编辑器内调整。

代码标记

PHP程序需使用 <?php ?> 来界定 PHP 代码,在HTML页面中嵌入纯变量时,可以使用 <?php echo $variablename;?> 这样的形式。
注意:为了使代码规范化和标准化,开发中禁止使用 <? ?><?=$variablename?> 这种速记形式。

注释

注释是对于那些容易忘记作用的代码添加简短的介绍性内容。请使用 C 样式的注释“/* */”和标准 C++ 注释“//”。

例如:

开发留下的临时代码和调试代码必须添加注释,以免日后遗忘。所有临时性、调试性、试验性的代码,必须添加统一的注释标记“//debug”并后跟完整的注释信息,这样可以方便在程序发布和最终调试前批量检查程序中是否还存在有疑问的代码。

例如:

书写规则

大括号{}、if和switch

首括号与关键词同行,尾括号与关键字同列;
if 结构中,else 和 elseif 与前后两个大括号同行,左右各一个空格。另外,即便 if 后只有一行语句,仍然需要加入大括号,以保证结构清晰;
switch 结构中,通常当一个 case 块处理后,将跳过之后的 case 块处理,因此大多数情况下需要添加 break。break 的位置视程序逻辑,与 case 同在一行,或新起一行均可,但同一 switch 体中,break 的位置格式应当保持一致。
以下是符合上述规范的例子:

运算符、小括号、空格、关键词和函数

每个运算符与两边参与运算的值或表达式中间要有一个空格;
左括号“(” 应和函数关键词紧贴在一起,除此以外应当使用空格将“(”同前面内容分开;
右括号“)”除后面是“)”,其他一律用空格隔开它们;
除字符串中特意需要,一般情况下,在程序以及HTML中不出现两个连续的空格;
任何情况下,PHP程序中不能出现空白的带有TAB或空格的行,即:这类空白行应当不包含任何TAB或空格。同时,任何程序行尾也不能出现多余的TAB或空格;
每段较大的程序体,上、下应当加入空白行,两个程序块之间只使用1个空行,禁止使用多行。
程序块划分尽量合理,过大或者过小的分割都会影响他人对代码的阅读和理解。一般可以以较大函数定义、逻辑结构、功能结构来进行划分。少于15行的程序块,可不加上下空白行;
说明或显示部分中,内容如含有中文、数字、英文单词混杂,应当在数字或者英文单词的前后加入空格。
根据上述原则,以下举例说明正确的书写格式:

函数定义

参数的名字和变量的命名规范一致;
函数定义中的左小括号,与函数名紧挨,中间无需空格;
开始的左大括号与函数定义为同一行,中间加一个空格,不要另起一行;
具有默认值的参数应该位于参数列表的后面;
函数调用与定义的时候参数与参数之间加入一个空格;
必须仔细检查并切实杜绝函数起始缩进位置与结束缩进位置不同的现象;
例如,符合标准的定义:

不符合标准的定义:

引号

由于PHP中单引号和双引号具有不同的含义,因此在使用时有如下原则:

在能使用单引号的情况下,禁止使用双引号。
字符串为固定值,不包含换号、制表等特殊转义时,需使用单引号。
字符串作为数据索引时,需使用单引号。
字符串不需要带入变量,需使用单引号。
数据库SQL语句中,所有数据必须加单引号,无论数值还是字串,以避免可能的注入漏洞和SQL错误。

数据库操作

为保证数据操作安全,数据库操作有以下处理及书写原则:

所有数据库操作时必须使用PDO操作
所有SQL查询关键字大写,方便代码审查
所有SQL对象(表名,字段名,索引名等)必须用反引号包括
所有编码参数查询,必须使用PDO的参数绑定机制处理
不能绑定参数处理的查询(唯一的例外是 IN () 语句),必须处理好变量检测及字符串转义

这是一个完整的数据库操作示例:

命名原则

命名是程序规划的核心。古人相信只要知道一个人真正的名字就会获得凌驾于那个人之上的不可思议的力量。只要你给事物想到正确的名字,就会给你以及后来的人带来比代码更强的力量。
名字就是事物在它所处的生态环境中一个长久而深远的结果。总的来说,只有了解系统的程序员才能为系统取出最合适的名字。如果所有的命名都与其自然相适合,则关系清晰,含义可以推导得出,一般人的推想也能在意料之中。
就一般约定而言,类、函数和变量的名字应该总是能够描述让代码阅读者能够容易的知道这些代码的作用。形式越简单、越有规则,就越容易让人感知和理解。应该避免使用模棱两可,晦涩不标准的命名。

变量、函数名

变量、函数名一律为小写格式;
以标准计算机英文为蓝本,杜绝一切拼音、或拼音英文混杂的命名方式;
变量命名只能使用项目中有据可查的英文缩写方式,例如可以使用 $data 而不可使用 $data1、$data2 这样容易产生混淆的形式,应当使用 $trade、$product 这样一目了然容易理解的形式;
可以合理的对过长的命名进行缩写,例如 $bio($biography),$tpp($threadsPerPage),前提是英文中有这样既有的缩写形式,或字母符合英文缩写规范;
必须清楚所使用英文单词的词性,在权限相关的范围内,大多使用 $allowXxx 或 $isXxx 的形式,前者后面接动词,后者后面接形容词。

类和接口名

类和接口的命名采用混合大小写字母的Pascal命名法
具体描述为:首字母大写,后续的每个单词也需要大写首字母。如:MySQLConnector、CacheProvider。
接口的命名与类相似,但需要以大写字母“I”开头,以作区分。
对象成员的命名则采用混合大小写字母的Camel命名法
具体描述为:公有成员及保护成员应首字母小写,后续的每个单词首字母大写
私有成员除需保持共有成员的命名方式外,还需要以下划线“_”开头,以作区分。

常量

常量应该总是全部使用大写字母命名,必要的情况下,可使用划线来分隔单词;
PHP 的内建值 true、false 和null必须全部采用小写字母书写。

变量的初始化与逻辑检查

任何变量在进行累加、直接显示或存储前必需进行初使化 ,例如:

判断一个无法确定(不知道是否已被赋值)的变量时,可用empty()或isset(),而不要直接使用if($switch)的形式。
empty()和isset()的区别为:请参阅PHP手册。
如果已经使用 unset() 释放了一个变量之后,它将不再是 isset()。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是一个 NULL 字节(”\0”)并不等同于 PHP 的 NULL 常数。
判断一个变量是否为数组,请使用is_array(),这种判断尤其适用于对数组进行遍历的操作,例如foreach(),因为如果不事先判断,foreach()会对非数组类型的变量报错;
判断一个数组元素是否存在,可使用isset($array[‘key’]),也可使用empty()。

安全性

    PHP中的变量不并不像C语言那样需要事先声明,解释器会在第一次使用时自动创建他们,同样类型也不需要指定,解释器会根据上下文环境自动确定。从开发人员的角度来看,这无疑是一种极其方便的处理方法。一个变量被创建了,就可以在程序中的任何地方使用。这导致的结果就是开发人员工经常不注意初始化变量。因此,为了提高程序的安全性,我们不能相信任何没有明确定义的变量。所有的变量在定义使用前要初使化以防止恶意构造提交的变量覆盖程序中使用的变量。
    不要相信任何客户端提交的数据是安全的。(包括:$_GET、$_POST、$_COOKIE、$_FILES、$_SERVER、$_REQUEST)

包含调用

包含调用程序文件,请尽量使用require,以保证效率。必要情况下,如难以避免的重复调用时可以使用require_once。
包含调用缓存文件,由于缓存文件无法保证100%正确打开,请使用 include_once 或 include。在必要时,可以使用 @include_once 或 @include 的方式,以忽略错误提示;

错误报告级别

软件开发调试和正式发布设置不同的报错级别。

在软件开发和调试阶段,打开错误报告以便能够报告程序中所有的错误、警告和提示信息,以帮助开发者检查和核对代码,避免大多数安全性问题和逻辑错误、拼写错误。

在软件发布时,关闭错误报告,以利于用户使用并将无谓错误提示信息降至最低。

其他注意要点

正则表达式操作请使用perl兼容正则表达式,即preg_ 系列的函数,以提升效率。
尽量使用高版本的函数。

数据库设计

表和字段命名

表和字段的命名以PHP编码中的命名规范为基本准则。
所有数据表名称,只要其名称是可数名词,则必须以复数方式命名,例如:members(用户表)、rules(规则定义表);
存储多项内容的字段,或代表数量的字段,也应当以复数方式命名,例如:params(parameters,参数个数)、views(查看次数)、replies(回复次数)。
当几个表间的字段有关连时,要注意表与表之间关联字段命名的统一,如 rule_keywords表中的rid与rules表中的rid。

代表id自增量的字段,通常用以下几种形式:

最常用的核心id,或经常在URL中进行调用的,尽量用简写的形式,例如rid、weid、uid;
有功能性作用,URL中偶尔用到的id,使用全称的形式,例如pluginid;
没有功能性作用,只为管理和维护方便而设的id,可以使用全称的形式,也可只将其命名为id。

字段结构

基于效率的考虑,所有字段均不能为空,即全部NOT NULL,可以设置默认值来代替。
预计不会存储非负数的字段,例如各项id、统计数等,必须设置为UNSIGNED类型。UNSIGNED类型比非UNSIGNED类型所能存储的正整数范围大一倍,因此能获得更大的数值存储空间。
储开关、选项数据的字段,通常使用tinyint(1)非UNSIGNED类型,少数情况也可能使用enum()结果集的方式。tinyint作为开关字段时,通常1为打开;0为关闭;-1为特殊数据,例如N/A(不可用),高于1的为特殊结果或开关二进制数组合。
任何类型的数据表,字段空间应当本着足够用,不浪费的原则。MEMORY/HEAP类型的表中,尤其要注意规划节约使用存储空间,这将节约更多内存。

SQL语句

所有SQL语句中,除了表名、字段名称以外,全部语句和函数均需大写,应当杜绝小写方式或大小写混杂的写法。例如select * from members;是不符合规范的写法。
很长的SQL语句应当有适当的断行,依据JOIN、FROM、ORDER BY等关键字进行界定。
通常情况下,在对多表进行操作时,要根据不同表名称,对每个表指定一个1~2个字母的缩写,以利于语句简洁和可读性。

运算与检索

数值运算一般比字符串运算更快。例如比较运算,可在单一运算中对数进行比较。而串运算涉及几个逐字节的比较,如果串更长的话,这种比较还要多。
如果串列的值数目有限,应该利用普通整型或emum类型来获得数值运算的优越性。
更小的字段类型永远比更大的字段类型处理要快得多。对于字符串,其处理时间与串长度直接相关。一般情况下,较小的表处理更快。对于定长表,应该选择最小的类型,只要能存储所需范围的值即可。例如,如果mediumint够用,就不要选择bigint。对于可变长类型,也仍然能够节省空间。一个TEXT 类型的值用2 字节记录值的长度,而一个LONGTEXT 则用4字节记录其值的长度。如果存储的值长度永远不会超过64KB,使用TEXT 将使每个值节省2字节。

文件及目录

文件命名

所有包含PHP代码的程序文件或半程序文件,应以小写.php作为扩展名,而不要使用.phtml、.php3、.inc、.class等作为扩展名。

普通程序

能够被URL直接调用的程序,例如home.php、index.php、forum.php,直接使用程序名+.php的方式命名

函数库和类库程序

分别以小写 xxxx.func.php 和 xxxx.class.php的格式命名书写。函数库和类库程序只能被其他程序引用,而不能独立运行。其中不能包含任何流程性的、不属于任何函数或类的程序代码。

空目录索引

请在所有不包含普通程序(即能够被URL直接调用的程序)的目录中放置一个1字节的index.html文件,内容为一个空格,以避免当http服务器的Directory Listing打开时,服务器文件被索引和列表。

PS:本文档会不定期更新。

您可能还喜欢...