2017年2月

PHP 编码规范

PHP 编码规范

当多人协作编码时,一份共同遵守的编码规范必不可少。它有利于阅读和编写代码,既可以提高新成员熟悉代码的效率,也可以提高老成员编码的效率。

如果以下规范与框架规范冲突,则以框架规范为准。

本文档中使用了大量的“能愿动词”,说明如下:

  • 必须:绝对,严格遵循,请照做,无条件遵守;
  • 一定不能:禁令,严令禁止;
  • 应该:强烈建议这样做,但不强求;
  • 不该:强烈不建议这样做,但不强求;
  • 可以:更多的选择。

1. 命名

变量名、类的属性名 必须 使用小驼峰形式(如 $varName)。

常量名中所有字母 必须 大写,单词间 应该 以下划线分隔。

文件夹名所有字母 应该 使用小写字母,单词间 应该 以下划线分隔。

类名 必须 使用大驼峰形式(如 ClassName)。

定义类的文件名 应该 与类名相同,或者包含类名,同样 应该 使用大驼峰形式。

方法名 必须 使用小驼峰形式。

PHP 的关键字 必须 全部小写。

系统常量(true, false, null必须 小写。

2. 基础规范

代码 必须 使用 4 个空格符而不是 Tab 键进行缩进。

每行代码的字符数 应该 控制在 120 个以内。

类和方法的起始花括号({必须 在声明后自成一行,结束花括号(}必须 在代码主体后自成一行。

类的属性和方法 必须 添加访问修饰符(private, protected, public),abstractfinal 必须 写在访问修饰符之前,而 static 必须 写在访问修饰符之后。

<?php

abstract class ClassName
{
    protected static $fooVar;

    abstract protected function baz();

    final public static function barShow($a, $b = null)
    {
        // 方法主体
    }
}

赋值符号(=)的左右 必须 有且只有一个空格。

取反符号(!)后 必须 有一个空格。

纯 PHP 代码文件 应该 省略末尾的结束标签(?>)。

非空行后 不该 有多余的空格。

每行 一定不能 存在多条语句。

文件 应该 以一个空白行作为结束。

字符串 应该 使用单引号。

3. 编码风格

3.1 类、属性和方法

关键词 extendsimplements 必须 写在类名称的同一行。

<?php

class ClassName extends ParentClass implements ImplementName
{
    // 这里面是常量、属性、类方法
}

implements 的继承列表也 可以 分成多行,但每个继承接口名称都 必须 分开独立成行,包括第一个。

<?php

class ClassName extends ParentClass implements
    ImplementName1,
    ImplementName2,
    ImplementName3
{
    // 这里面是常量、属性、类方法
}

每个属性都 必须 添加访问修饰符。
一定不能 使用关键字 var 声明一个属性。
每条语句 一定不能 定义超过一个属性。
不该 使用下划线作为前缀,来区分属性是 protectedprivate

所有方法都 必须 添加访问修饰符。
不该 使用下划线作为前缀,来区分方法是 protectedprivate
方法名称后 一定不能 有空格符,参数左括号后和右括号前 一定不能 有空格。
参数列表中,每个逗号后面 必须 要有一个空格,而逗号前面 一定不能 有空格。
有默认值的参数,必须 放到参数列表的末尾。

<?php

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // 方法主体
    }
}

訪問修飾符 必須 按最小訪問原則。例如只在本類中使用的方法,必須使用 private;當該方法需要被外部訪問時,再改為 public

3.2 控制结构

控制结构的关键字(如 if)后 必须 有一个空格,而调用方法、函数的左括号前 一定不能 有空格。
控制结构的起始花括号 应该 写在声明的同一行,而最后一个结束花括号 必须 在主体后自成一行。
控制结构的左括号后,右括号前 一定不能 有空格。
结构体主体 必须 要有一次缩进。
注意,控制结构的花括号并不总是单独成行。

if 条件语句

<?php

if ($expr1) {
    // if 代码块
} elseif ($expr2) {
    // elseif 代码块
} else {
    // else 代码块
}

应该 使用关键词 elseif 代替所有 else if
主体部分,必须 使用花括号括起来,即使只有一句。

switch 语句

<?php

switch ($expr) {
    case 0:
        echo '第一种情况, 带有 break';
        break;
    case 1:
        echo '第二种情况';
        // no break
    case 2:
    case 3:
    case 4:
        echo '第三种情况, 直接 return';
        return;
    default:
        echo '默认情况';
        break;
}

case 语句 必须 相对 switch 进行一次缩进,而 break 语句以及 case 内的其它语句都 必须 相对 case 进行一次缩进。
如果存在非空的 case 直穿语句,主体中 必须 有类似 // no break 的注释。

while 和 do...while 语句

<?php

while ($expr) {
    // 循环主体
}

do {
    // 循环主体
} while ($expr);

for 语句

<?php

for ($i = 0; $i < 10; $i++) {
    // 循环主体
}

foreach 语句

<?php

foreach ($iterable as $key => $value) {
    // 循环主体
}

try...catch 语句

<?php

try {
    // 主体代码
} catch (FirstExceptionType $e) {
    // 异常处理代码
} catch (OtherExceptionType $e) {
    // 异常处理代码
}

3.3 闭包

关键词 function 后以及关键词 use 的前后都 必须 要有一个空格。
开始花括号 必须 写在声明的同一行,结束花括号 必须 紧跟主体结束的下一行。

<?php

$closureWithArgs = function ($arg1, $arg2) {
    // 主体
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // 主体
};

参数列表以及变量列表 可以 分成多行,这样,包括第一个在内的每个参数或变量都 必须 单独成行,而列表的右括号与闭包的开始花括号 必须 放在同一行。

<?php

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // 代码主体
};

3.4 命名空间

namespace 声明后 必须 插入一个空白行。
所有 use 必须namespace 后声明。
每条 use 声明语句 必须 只有一个 use 关键词。
use 声明语句块后 必须 要有一个空白行。

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// 更多的代码...

3.5 注释与空行

单行注释 应该 放在行末,与代码之间 应该 保留 2 个空格,而较长的注释,应该 放在相应代码的上一行;注释符号(//)与注释之间 应该 保留 1 个空格。

较复杂的代码,应该 详细说明。

<?php

/**
 * 算法标题
 *
 * 首先,调用...取得...数据
 * 其次,对...数据进行循环处理,得到...
 * 最后,按...格式输出数据
 */

清楚明了的代码 不该 增加注释:

<?php

$criteria = new CDbCriteria;
// 仅获取id,parentid字段
$criteria->select = 'id,parentid';
// 排除已删除节点
$criteria->addCondition('is_delete=0');

$list = $modelClassName::model()->findAll($criteria);

代码块之间 应该 用一个空行分隔,如类的方法之间使用一个空行分隔。

附0 开发工具推荐

PhpStorm
PHPDesigner
PhpED

附1 Git 使用

提交时简明扼要地描述所变更代码的主要内容
至少形成一个基本逻辑再提交
不相关的修改应该分开提交
不必要的修改不要提交(如调试时多加了个空行,提交时查看变更内容可避免)
开发周期较长(超过一周)的需求应该新建一个分支

提交信息格式:
修改Bug:BF(###): xxxxxxx
完成需求:PR(###): xxxxxxx

参考文档

  1. PSR - PHP标准规范