[总结] PHP代码规范草案0.0.1版

草案 0.0.1

一。Zend

Zend Framework 编码规范

http://bbs.phpchina.com/viewthread.php?tid=142789

二。常规规范

1.变量命名与类的命名
(1) 类型 + 变量名: $inum
基于PHP语言弱类型的特点,以匈牙利命名法为参考,但国人不习惯大写字母,所以纯小写,为基本规范。
一个类型字符+命名的方式,比如 $susername
s代表字符串,i代表整型,a代表数组,o代表对象, r代表资源, b布尔型, d日期,例子:



1. $inum = 55;
2. $itotal = 110;
3. $susername = 'root';
4. $spassword = '123456';
5. $rlink = mysql_connect('localhost', 'root', '123456');
6. $odb = new dbstuff();
7. $anumber = array(1, 2, 3, 4, 5);
8. $ddate = '2010-06-04';




复制代码



 



特殊常用的少数变量,可以不用书写前缀,比如:

$uid, $sid, $sql, $row, $db, $i, $j, $k, $v或者$key, $value



这种书写方式缺点:略需一点适应成本,但习惯后对程序员的类型思维有帮助,对团队开发和代码阅读调试意义重大。


(2) 常用的命名及数据库设计字段类型及长度字符串类型一般没有默认值,而非主键的数值类型,非空,默认值为0。

username 用户名, char(16)

password 密码, char(32)

email 邮件, char(50)

dateline 时间,int(10)

register 注册

login 登陆

adminid 管理员id, 某某id的命名,采用 名字+id的方式,


比如groupid,

常用的id可用缩写替代:比如

uid 用户id, mediumint(8)

sid SESSION id

displayorder 文章或类别现实顺序 smallint(6), -2为未审核, -1 忽略, 0以上为正常顺序。

基本规范摘取了Discuz设计数据库的用法,效率是有目共睹的。



(3) 表示总数的命名,请用复数形式,如:

$iviews 总浏览数

$ireplies总回复数

$iclicks总点击数


(4) 表示权限判断的命名,请在前面附加allow,如

$ballowview

$ballowpost

$ballowvisit


(5) 常规变量定义一般不使用下划线_,中划线- 和大写字母,特殊字符等。



(6) 类名

类名在使用中经常遇到命名空间的问题,因此,类名的命名规范除了要遵循普通命名规则以外,还需在类名前附加产品和所属模块名称。

该名称最好与表名前缀一致。如:

例如:

1. class cdb_trade_cart {
2.     ……
3. }



复制代码




 



(7) 字段名采用匈牙利命名法的好处:

程序中出现SQL语句时,陌生字段基本不用去查看表结构。



如:

susername,

spassword,

idateline



2. 书写细节规范

(1) 空格:

A. 等号或其他运算符两边各有一个空格,比如

$inum = 55;

$inum = 55 + 66;

B. 并列的各项中间用逗号分隔,其后要有一个空格。如:

array(1, 2, 3)而非array(1,2,3)

C. if语句中,if关键字后没有空格,而小括号的条件之后有空格,比如

1. if($inum == 55) {
2.     ……
3. }



复制代码




 


(2) 断行,如果语句过长(默认为80字符)时,需要断行譬如:


1. array(
2.   'a' => '这是一个字符串',
3.   'b' => '这是第二个字符串',
4.   'c' => '这是第三个字符串'
5. )



复制代码





 



(3) 缩进

以4个空格为一个缩进单位为准。

两种方案:

A. 统一用Tab键,在代码书写完发布前,用编辑器功能统一替换为4个空格

B. 手动敲4个空格,或者编辑器功能自定义


(4) 大括号与小括号

大括号的两种方案:

A.


    1. if() {
    2.     ……
    3. } elseif() {
    4.     ……
    5. } elseif() {
    6.     ……
    7. } else {
    8.     ……
    9. }


    复制代码





     


    B.

    1. if() 
    2. {
    3.     ……
    4. }
    5. elseif() 
    6. {
    7.     ……
    8. }
    9. else 
    10. {
    11.     ……
    12. }



    复制代码





     


    小括号,在运算符优先级容易产生混淆的地方,必须用小括号括起来,在变量拼接时,如果出现某个变量值作为字符串的一部分,或者模板中复杂嵌套,要用大括号{}括起来。

    如 $sql = "SELECT uid FROM {$tablepre}members";

    或 模板中:{$aarray[$key][sec]}


    (5) 单引号,双引号与SQL

    尽量使用单引号,比如

    $susername = 'root';

    在写数组的索引时,必须使用单引号:

    如 $alist['key']的方式,而不是$alist[key]。


    单双引号的嵌套组合,SQL语句(关键字需大写)拼接的推荐写法。字段名可使用``号区隔。

    A. $sql = "SELECT `uid` FROM {$tablepre}members WHERE `username` = '$gsusername' LIMIT 1";

    外层是双引号,所以里面在单引号内的变量能够解析。

    单引号表明里面的值是个字符串。

    这样的拼接方式好处在于易读性。

    B. $sql = 'SELECT `uid` FROM '.$tablepre.'members WHERE `username` = /''.$gsusername.'/' LIMIT 1';

    这样书写的好处是效率会高点,但是语句比较不易读,需要转义字符,稍微繁复。


    其他常用拼接:

    HTML时,$sform = '<input type="text" name="username" />';

    3. 程序语句段书写规范

    (1) 先按先后依赖关系分顺序,再按功能分隔语句段。

    如关于 $sid 有50行语句段A,前面依赖通用功能定义。

    那么通用功能定义语句应在A段代码之前。

    A段代码,和其他功能段代码,都应该成块状。


    比如500行文件,可分为段A、B、C、D、E等。

    各段之间用两个空行区隔开


    (2) 功能段内部语句段顺序

    A. 变量赋初值

    B. 确定主要功能逻辑段所用到的变量值

    C. 主功能逻辑段

    D. 返回、输出或其他操作


    (3) 后台管理功能块或其他功能块的基本划分:

    A. 用表单的提交元素判断切分开逻辑层与表现层

    如 <input type="submit" name="registersubmit" />

    那么,在代码中通过



    1. $pssubmit = $_POST['registersubmit'];
    2. if(empty($pssubmit)) {
    3.     //表现层代码
    4. } else {
    5.     //逻辑层代码
    6. }




    复制代码




     


    B. 逻辑层可通过表现层的输入表单元素的name 值来区隔开增删查改。

    如<input type="text" name="gender[]" value="" />,则判断数组$pagender是否有值来进行更改操作

    <input type="checkbox" name="delete[]" value="" />, 则判断数组$padelete是否有值来进行删除操作

    ……

    (4) 循环体

    A. 在循环体内,不允许出现重复计算。

    如:


    1. $sstring = 'abcdef';
    2. //低效率的写法
    3. foreach($i = 0; $i < strlen($sstring); $i++) {
    4.     ……
    5. }
    6. //高效写法应该是:
    7. $ilength = strlen($sstring);
    8. foreach($i = 0; $i < $ilength; $i++) {
    9.     ……
    10. }




    复制代码






    B. 在函数循环体内实现接收参数可以是单值,也可以是数组。如(参考discuz):


    1. function decho($input) {
    2.     if(is_array($input)) {
    3.         foreach($input as $v) {
    4.             decho($v);
    5.         }    
    6.      } else { 
    7.        echo $input;
    8.      }
    9. }




    复制代码






    C. 尽量减少循环次数,如以下例子:

    1. function neworder($aarray) {
    2.     sort($aarray);
    3.     $inum = count($aarray);
    4.     $iloop = round($inum / 2);
    5.     for($i = $inum; $i > $iloop; $i--){
    6.         $anewarray[] = $aarray[$i - 1];
    7.         $anewarray[] = $aarray[$inum - $i];
    8.     }
    9.     if($inum % 2 <> 0) {
    10.         $anewarray[] = $array[floor($inum / 2)];
    11.     }
    12.     print_r($anewarray);
    13.     $array = $anewarray;
    14. }
    15. $aarray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
    16. 
    17. neworder($aarray);




    复制代码




    4。使用建议:(1) 程序根目录定义

    基本思路以程序中必然包含的公用文件为基准,比如include目录下的common.inc.php

    define('ROOT', substr(dirname(__FILE__), 0, -7));


    每个入口脚本必须在开头包含此行语句,(-7为你公用包含文件所在目录名长度)


    (2) require_once和include_once

    基本不使用 include或require, 统一使用require_once和include_once

    如非临时文件包含,则必须使用require_once,否则使用include_once如缓存文件,模板编译文件等。

    为区别开,require_once 和 include_once 不加小括号。写法如下:


    require_once ROOT . './include/xxxx.php';



    路径书写前,必须加'./',必须使用/,而不使用/。



    (3) 流程建议

    A. 使用以下方式来控制开关。


    if(in_array($smodel, array('cms', 'bbs', 'sns'))) {
        ……
    }



    B. 逻辑分支控制

    纯数字或者固定值返回的控制用switch ... case



    逻辑分支判断条件比较复杂时,使用 if ... else



    逻辑分支结构都以函数为分割的,可采用如下方式:


    function a() {
    
    
    }
    function b() {
    
    
    }
    
    
    //下面的值,可以是任意传参。这样效率分支开销效率比较高。
    $scase = 'a';
    
    
    $scase();


    5. 文件目录命名

    (1) 空目录索引

    除主目录以外的所有目录放置一个1字节的index.htm来防止服务器目录列表打开时,服务器动态文件脚本被下载。

    (2) 常用的目录

    config文件夹,常用配置文件

    template 模板文件夹

    下面有default文件夹,表示程序默认模板

    language 语言包文件夹

    admin 后台管理目录

    include/source 文件夹,主要函数包含文件

    image 图片文件夹

    js Javascript文件夹

    API应用程序接口

    install安装目录


    data 生成文件的临时文件夹,下有几个目录:

            cache文件缓存

            log 日志文件

            template 模板编译文件缓存

            ……



    (3) 文件名,小写字母+下划线

    扩展名:php文件用.php,模板文件使用.htm,JavaScript


    文件使用.js

    A.function_xxxx.php 表示函数包含文件

    B.class_xxxx.php 表示类文件

    C.不带下划线的字母文件名,表示功能主入口文件。

    比如 index.php

    D.某功能模块下,子功能文件名定义:

    模块名_子功能.php,

    如:member_register.php表示用户模块的注册功能文件。

    language_friend.php表示朋友模块的语言包。


    (4)PHP文件格式

    乱码(切忌使用记事本)。        


            标记:PHP文件必须使用 <?php,文件结尾不加?>,以防止空行带来的逻辑问题。        



            行分割:使用 /n 换行符,不可使用 /r/n 或 /r。


    6. 注释


    有以下几种注释

    A. 文档头部说明注释格式


    1. /***
    2. *  这是注释
    3. *  是注释
    4. *  注释
    5. */



    复制代码




     


    B. 单行注释,必须现在所注释的前一行或简短写在行末


    1. //这是注释,下面是变量赋值的例子
    2. $inum = 55;
    3. 
    4. $inum = 55; //行末注释



    复制代码





     



    C. 多行注释


    1. /*
    2.   这是注释
    3. */



    复制代码





     



    D. 尽量不用 #、///等方式进行注释,

    E. 代码书写完以后,冗余调试代码的注释必须删除掉,只剩简洁的代码功能描述注释


    我希望定一个开放性的规则,大家参与进来,并修订他


    6. 代码提交

    所有代码提交必须使用SVN或CVS等版本维护功能提交,不得使用FTP直接上传。

    SVN同步,可以采用远程共享同一台机子的数据库。

    或者同步data目录

    也可遵循统一的命名,如统一的数据名、表名、域名、字段名、用户名、密码等。

    然后基本数据库各本地拷贝一份。




    我希望定一个开放性的规则,大家参与进来,并修订他,然后希望能达成共识,签署一些同意书包含:

    1。我愿意在我有生之年遵循大家共同制订的PHP规范,并努力推广他,无论生老病死。。。。富贵贫困。。。

    2。我愿意对已有规范进行建议性修订和贡献良好的规范。

    3。我愿意遵循讨论出来的结果,哪怕和我的现行语法规范相违背。

    4。我愿意在团队中使用此规范。

    5。虽然他有很多不完善的地方,但只要他是开放的体系,总有一天他会完善的,所以我愿意遵循这种相对完善的团队规范。


    当然,作为phpchina而言,我会尽量联系国内php团队去组织完善这项规范。


    仅此,题记,初摸爬行,望谅。