转载请注明:转自http://blog.csdn.net/qinzhiji1234/article/details/44123525
学习PHP开发也有一两年之久了,一直以来都没有说要去写点什么东西,真是有点不应该。确实,写博客可以让自己总结自己在开发中所遇到的问题和一些解决的经验,然后将经验分享出去,这样也遵循Apache Licence了嘛(^∇^),那么本文是我自己在学习PHP时所使用的一些编码规范:
- 文件格式
- 命名规范
- 注释规范
- 代码风格
文件规范
刚接触PHP时,确实没有注意到这一点,以为文件名也就跟JSP之类一样,毕竟都是Web开发脚本语言嘛,在使用了PHP Strom(创建文件时会有创建文件类型而自动以改类别命名)之后才逐渐发现原来文件命名也有很多规则。
文件和目录
很多初学者都会使用一些拼音或者无意义的字母来命名,这不能说是错误的,因为程序本身并没有报错,但这是不规范的,在程序不断开发过程中,这种命名规则可能致使程序产生Bug。在所有PHP命名中都应该使用有意义的英文命名,可以且只允许出现字母、数字、下划线和中划线。毋庸置疑的,文件都必须以’.php‘结尾,当然除了模版文件。多个词间使用驼峰命名法。
文件命名
规则:文件名+.文件类型+’.php’ 。类和接口文件最常用此类规则。
例如:
1. 类文件
DemoTest.class.php
2. 接口文件
DemoTest.interface.php
3. 其它安装各自方式的文件
demoTest.{style}.php
4. 其它一些文件
demoTest.inc.php
zend/demo.lib.php
当然也有不使用文件类型作为命名的,例如:index.php
、Laravel中app/config.php、ThinkPHP中ThinkPHP/Conf/convention.php等等。
文件标记
所有PHP文件代码均适用完整PHP标签,不提倡使用短标签:
<?php
echo '这里使用了完整PHP标签!';
?>
<?
echo '不建议使用这里的PHP短标签!';
?>
使用PHP短标签容易和XML混淆,并且不是所有版本的PHP和服务器都默认支持或打开短标签选项的(在PHP5.4之后的版本,其配置文件中的短标签选项对短标签使用不起影响作用)。
当PHP文件中只含有PHP代码时,可使用单标签,即省略’?>‘。这样做的好处是为在标签之外的空格或者其他字符影响到代码。例如,test.php在PHP完整标签之外留有空格或者换行。
test.php文件内容:
<?php
$test = 'test';
?>
>(代表回车换行)
>
在index.php中引入了test.php代码
<?php
include 'test.php';
session_start();
?>
此时,就会看到一个警告:"...Cannot send session cache limiter-headers already sent...",之所以出现这个警告,是因为在session_start()之前输出了一些看不到的字符。
实际上这个问题只有在php.ini中不开启压缩或缓存输出时才会出现
zlib.output_compression = off
output_buffering = off
文件目录结构
在开发规范、独立的PHP项目时,使用规范的文件目录结构,有利于提高项目逻辑结构的合理性,对于扩展和合作以及团队开发均有好处。
通常情况下的,一个完整独立的PHP项目,其文件目录结构如下:
|--app // 独立应用目录
|--manage // 后台管理文件存放目录
|--class // 单个类文件,公用的类文件,如工具类
|--conf/inc // 配置文件目录
|--data // 数据文件目录
|--doc // 程序相关文档
|--htdocs // document_root
|--images // 图片文件目录
|--css // CSS样式文件目录
|--js // JavaScript文件目录
|--lib // 公共类库
|--template // 模版文件目录
|--temp // 临时文件目录
|--cache
|--session
|--template_c
|--other
|--upload // 上传文件目录
如果使用框架来做项目时,那得遵循框架所定义的目录结构。
例如:ThinkPHP 3.2框架
|--index.php // 入口文件
|--README.md // README文件
|--Application // 应用目录
|--Public // 资源文件目录
|--ThinkPHP // 框架系统目录(可以部署在非web目录下面)
|--Common // 核心公共函数目录
|--Conf // 核心配置目录
|--Lang // 核心语言包目录
|--Library // 框架类库目录
|--Think // 核心Think类库包目录
|--Behavior // 行为类库目录
|--Org Org // 类库包目录
|--Vendor // 第三方类库目录
|-- ... // 更多类库目录
|--Mode // 框架应用模式目录
|--Tpl // 系统模板目录
|--LICENSE.txt // 框架授权协议文件
|--logo.png // 框架LOGO文件
|--README.txt // 框架README文件
|--index.php // 框架入口文件
命名规范
变量命名
PHP中的变量用一个美元符号($)后面跟上变量名表示,变量名区分大小写。一个有效的变量名由字母或下划线开头,后面更任意数量的字母、数字、下划线。按正常的正则表达式,它将被描述为:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*。
注:在此所说的字母是a-z,A-Z,以及ASCII字符从127到255(0x7f-0xff)。
// 正确的命名方式
$name = '以字母开头';
$_name = '以下划线开头';
$name1 = '带有字母和数字';
$user_1_test = '带有字母、数字和下划线';
$userName = '驼峰命名法';
$user_name = '下划线命名法';
$NAME = '常量';
$_GLOBAL['_userName_'] = '全局变量的键值必须以下划线开头,并以下划线结尾';
// 不正确的命名方式
$1 = '不能使用数字开头';
大部分情况下,普通变量使用驼峰命名法,并建议在变量前加上变量类型的前缀。不确定类型的变量以大写字母开头,函数参数不确定类型的变量以大写字母开头,其他地方的变量以小写字母开头。对于一些常见类型变量,按照约定命名,以避免使用常用关键字或者存在模糊意义的单词。变量应该以名词为主。
// 推荐使用
$sMyName // 字符串
$arrMyArray // 数组
$oMyObject // 对象
$resource // 资源
$flag // 布尔值
// 不推荐使用
$yes = false; // 不应该使用此类变量名,致使代码逻辑混乱
$sex; // 模糊意义,若为性别则命名为 $gender 。
函数方法命名
函数方法命名规则遵循驼峰命名法,命名既要有意义,又要简洁明了。建议采取动词或动词+形容词的命名方式。例如:
// 建议使用
function getUserName(){}
function showMsg(){}
//不建议使用
function getUserRoleByUserNameAndUserPassword($sUserName, $sUserPwd){}
// 应当缩写
function getUserRole($sUserName, $sUserPwd){}
类及接口命名
类及接口的命名规则遵循驼峰命名法,同时还有一些特殊的规则:
- 类名必须与文件名保持一致。
// MyClass.class.php
<?php
class MyClass {
}
?>
// Database.class.php
<?php
class Database {
}
?>
- 程序中所有类名唯一。
- 抽象类以Abstract开头。
AbstractCar.class.php
<?php
abstract class AbstractCar {
}
?>
- 接口命名必须加’i’字母为前缀,表示接口。
- 接口命名尽量保持与实现它的类名一致。
iDatabase.interface.php
<?php
interface iDatabase {
}
?>
数据库命名
在数据库命名中,一律使用小写字母规则。
- 数据表命名规则:
- 表名均使用小写字母;
- 表名使用统一的前缀,且前缀不能为空(模块化,且有效避免MYSQL保留字);
- 对于多个单词组成的表名,使用下划线间隔。
例如:
blog_user_info
blog_article
- 数据表字段命名规则:
- 全部使用小写字母;
- 多个单词不用使用下划线分割;
- 如果有必要,给字段加上表名首字母作为前缀;
- 避免使用关键字和保留字,除约定成俗之外。
例如:
表blog_user_info
uid
username
userpwd
opentime
time
from // 不建议使用,和保留字冲突
- 存储过程、触发器、event以及视图命名规则:
1. 存储过程以pro_开头;
2. 触发器以tri 开头;
3. Event调度以event_开头;
4. 视图以view_开头。
例如:
proc_syn_nike_name_friend
tri_blog_user_u
event_rank
view_blog_user
习惯与约定
循环体变量
通常情况下,变量名应该是要有意义的单词,但在循环体中的临时变量采用“I-N规则”。
<?php
function bubbleSort ($arrSortArray){
$cnt = count ($arrSortArray);
for ($i = 0; $i < $cnt; $i++){
for ($j = $count - 1; $j > $i; $j--){
if ($arrSortArray[$j] < $arrSortArray[$j -1])
{
$tmp = $arrSortArray[$j];
$arrSortArray[$j] = $arrSortArray[$j - 1];
$arrSortArray[$j - 1] = $tmp;
}
}
}
return $arrSortArray;
}
?>
在这个循环体中, i、 j这样无意义的变量是允许的,并且普遍被接受。
缩写
按照习惯,同时为了缩短变量长度,在不影响可读性到前提下,习惯对变量进行缩写,常见于一些函数参数中。此规则也适用于PHP之外的代码,如JavaScript、数据库表字段命名等等。
例如:
Image ---> img
string ---> str
database ---> db
array ---> arr
count ---> cnt
temporary ---> temp 或者 tmp
password ---> passwd 或者 pwd
message ---> msg
魔术数字
魔术数字是指直接写在程式码里的具体数值。
一般认为程式码里不应该含有魔术数字,因为:
1. 数值的意义难以了解,比如一些专业的数字;
2. 数值需要变动,改动麻烦。
<?php
// 这段代码是指税后的价格
$priceTax = 1.05 * $price;
// 一旦改了税率之后,那么就需要修改程序。这里的1.05就是魔术数字
//修改为
define(TAX, 1.05);
$priceTax = TAX * $price;
?>
注释规范
程序注释
程序注释原则:
- 多行代码的注释应该放在代码前面,注释单行语句则放与语句末尾。
- 对于大段注释,使用
/**/
格式,通常在文件和函数注释中使用,而代码内部使用//
统一注释。 - 注释不宜太多,简单易懂的代码就不需要注释了。
<?php
/**
*
* 初始化过程
*
* @access public
* @return void
*/
function init(){
// 列表文件不存在,则重新编译
if (!is_file(DATA_DIR . 'list.php')){
APP::clear(); // 必须先删除缓存,防止数据不一致
APP::build();
}
// other things
}
?>
文件注释
文件注释通常放与文件头部,其内容包含文件版权、作者、编写日期、版本号等重要信息。文件注释主要遵循以下规则:
- 必须包含本程序的描述;
- 必须包含作者;
- 必须包含项目名称;
- 必须包含文件名称;
- 可以包含创建时间;
- 可以包含版本号;
- 可以包含重要的使用说明,例如类的调用方法、注意事项等。
<?php
/**
* Test项目
*
* LICENSE
* 本段代码来自于Test项目,遵循GNU自由软件协议
*
* --------------------------------
* 本项目是一个PHP测试项目,叫做Test
* --------------------------------
* @description 模型初始化,按需加载所需的资源
* @package __MODELINI__
* @copyright Copyright(c) 2014 - 2015 test Inc.
* @author tester tester@test.com
* @version 1.0
* @modify 优化了test方法,提高了效率。by:tester
*/
?>
需要注意的是,文件一定要加上作者信息,这样有利于划分代码责任,同时方便代码阅读者联系作者。另外,版本号需要随着每次更新进行修改,并加上modify注释,阐述每次修改都内容。
类与接口注释
类和接口的注释应当尽量简洁。一般习惯一个文件只包含一个类,在类注释中通常不需要再加上作者和版本等信息,只需加上可见性和简单的描述即可。如果文件注释已经足够详细了,可以不用给类写注释了。如果同时存在接口和接口的实现类,通常只在接口中进行注释。
函数方法注释
函数方法的注释写在其最前面,通常需要标明的信息主要是函数方法说明、可见性、参数类型和返回值类型。
例如:
<?php
/**
*
* 链接数据库
*
* @param string $sDbHost 数据库服务器地址
* @param string $sDbUser 数据库用户名
* @param string $sDbPwd 数据库密码
* @param string $sDbName 数据库名
* @param string $sCharset 数据库编码(默认为UTF8)
* @access public
*
* @return void
*/
public function connectDb($sDbHost, $sDbUser, $sDbPwd, $sDbName, $sCharset = 'utf8'){
}
?>
标注
IDE支持一些特殊的注释,可以列出整个项目中的特殊注释,方便后期维护和代码检查。
例如:
// @fixMe 表示需要修复项。
// @todo 表示需要完善的地方。
@deprecated 表示代码不推荐或废弃使用的函数方法
@overload 表示对该方法进行重载
代码风格
缩紧和空格
最开始学习和使用PHP开发是在Ubuntu上,使用Vi作为开发编辑器,因此,经常需要自己去缩紧代码,和在适当的地方留有空格,这样才能看清楚自己写的代码。对于初学者,我还是建议不要使用大型集成IDE,因为这些事情IDE都会帮你做了,以致你不能养成良好的编程习惯。以后在做项目的时候,到要使用这些IDE工具,一方面开发速度提高,另一方面它们都具有检查代码正确性的功能。说说代码缩紧和空格的一些规则:
- 使用4个空格作为缩紧,而不是使用table缩紧(一些IDE默认使用table,因此需要修改它);
- 变量赋值时,等号左右留出空格(在IDE代码风格设置中还可以设置函数方法、if、switch等后面的空格和其括号内的空格)。
为了最大减轻工作量,保持代码美观,在使用大型IDE开发时,首先设置好代码风格,然后使用IDE快捷键对代码进行格式化。
语句断行
代码断行规则:
- 尽量保证程序语句一行就是一句;
- 尽量不要使一行的代码太长,一般控制在80字符以内(大型IDE默认设置);
- 若一行代码太长,请使用类似”.=”的方式断行书写;
- 执行数据库的SQL语句操作时,尽量不要在函数内写SQL语句,而先用变量定义SQL语句,然后在执行操作的函数中调用预先定义的变量即可。
例如:
<?php
$sSql = "SELECT username,password,address,age,gender FROM user_info"
$sSql .= " WHERE username = ${user}";
$hRes = mysql_query($sSql);
?>
良好的习惯
- 多使用PHP中已经存在的常量,而不要自己定义;
例如:换行
// 不建议使用
echo $sMsg . "\r\n";
// 推荐使用
echo $sMsg,PHP_EOL;
PHP_EOL时PHP中预定的一个常量,表示一行结束,随着操作系统不同,使用PHP_EOL会让代码更具有可移植性。
- 在echo中使用逗号作为字符串连接符,比使用点号代码更美观;
- 单引号的效率高于双引号,但是不要刻意使用单引号,一则不美观,再则二者在用法上有区别,稍有不慎就会犯错误。尽管echo语句效率更高,但也要学着使用printf函数;
// 丑陋的echo
echo $sUser.'的总成绩为:'.$sTotalScore.' ,平均成绩为:'.$sAvgScore.' 。';
// 优雅的print
$format = '%的总成绩为:% ,平均成绩为:% 。';
printf($format,$sUser,$sTotalScore,$sAvgScore);
//printf函数最常用到的地方就是拼接SQL语句
- 更详尽的注释;
注释是一门艺术,好的注释可以比代码更精彩。不用担心效率问题,一则注释对代码影响并不大,其次是在产品发布的时候会对注释进行批量删减。 - 不要滥用语法糖。
语法糖就是语言中的潜规则,即不具有普遍代表性的语法。少量使用语法糖会尝到甜头,大量使用则是一种灾难。