以下代码风格指南针对于开发 Yii 2.x 核心代码和官方扩展。 如果你想向核心代码 pull request,你应该考虑遵循本指南。 我们不强迫你在自己的应用中使用本代码风格,你可以自由选择你喜欢的。
你可以在这里获取 CodeSniffer 的配置文件:https://github.com/yiisoft/yii2-coding-standards
- 概览
总体上我们采用 PSR-2 兼容风格,所以所有符合 PSR-2 标准的代码也符合我们的代码风格。
- 文件 必须 使用
<?php
或<?=
标签。 - 文件末尾应该空一行。
- 文件中的 PHP 代码 必须 使用无 BOM 的 UTF-8 字符编码。
- 代码 必须 使用 4个空格缩进,而不是 tab。
- 类名 必须 使用首字母大写的驼峰法
StudlyCaps
。 - 类常量的声明 必须 全部大写并以下划线作分隔符。
- 方法的声明 必须 使用首字母小写的驼峰法
camelCase
。 - 属性的声明 必须 使用首字母为小写的驼峰法
camelCase
。 - 私有属性的声明 必须 由一个下划线开始。
- 始终使用
elseif
,而不是else if
。
- 文件
- PHP 代码 必须 使用
<?php
或<?=
标签,不可以
使用包括<?
在内的其它任何标签。 - 纯 PHP 代码的文件应该省略
?>
关闭标签。 - 每行代码末尾
不可以
使用空格作为结束。 - 任何包含 PHP 代码的文件扩展名都应该为
.php
。
PHP 代码 必须 且只能使用 无 BOM
的 UTF-8
编码。
- 类名
类名的声明 必须 使用首字母为大写的驼峰法 StudlyCaps
声明, 例如 Controller
, Model
。
- 类和接口
下列说明中的“类”指的是所有“类”和“接口”。
- 类名的应该使用首字母为大写的驼峰法
StudlyCaps
。 - 左大括号始终应该写在类名的下一行。
- 每个类都应该有符合 PHPDoc 规范的文档块。
- 类中的所有代码都应该缩进一个 tab。
- 每个 PHP 文件中应该只包含一个类。
- 所有的类都应该有命名空间。
- 类名应该与文件名保持一致,类的命名空间应该与目录结构保持一致。
/**
* 文档
*/
class MyClass extends \yii\Object implements MyInterface
{
// 代码
}
类常量的声明 必须全部大写并以下划线作分隔符。 例如:
<?php
class Foo
{
const VERSION = '1.0';
const DATE_APPROVED = '2012-06-01';
}
- 声明一个公有属性应该使用关键字
public
显式的指明它。 - 公有和受保护类型的属性应该声明在类中的最上方,位于所有成员方法的前面。私有属性也应该声明在类中的最上方,但当它处理的数据只和类中很少一部分成员方法相关时,可以直接写在这些方法的前面。
- 一个类中属性声明的顺序从上到下应该为公有、受保护、私有。
- 从可读性角度考虑,属性的声明之间不该有空行,而属性和方法之间应该有2个空行。
- 私有属性的命名应该以一个下划线开始,后面是首字母为小写的驼峰法
camelCase
,如$_totalCount
。 - 公有类成员和普通独立变量的命名应该用首字母为小写的驼峰法
camelCase
,如$camelCase
。 - 使用描述性的命名,诸如
$i
、$k
之类模糊不清的最好不要使用。
例如:
<?php
class Foo
{
public $publicProp;
protected $protectedProp;
private $_privateProp;
}
- 函数和方法的命名应该用首字母为小写的驼峰法
camelCase
。 - 方法名本身应该是描述性的,用来表示这个方法的目的。
- 方法的声明应该始终使用
public
、protected
或private
修饰其可见性,不可以使用 PHP 4 风格的var
。 - 包裹方法的左大括号应该位于方法声明的下一行。
/**
* 文档
*/
class Foo
{
/**
* 文档
*/
public function bar()
{
// 代码
return $value;
}
}
@param
,@var
,@property
和 @return
必须要声明类型诸如 boolean
,integer
,string
,array
或 null
,你还可以使用类名诸如 Model
、 ActiveRecord
等。数组成员为对象时使用 ClassName[]
。
- 应该使用
__construct
而不是 PHP 4 风格的构造方法。
-
所有 PHP 内置类型和值都 必须 用小写。包括
true
,false
,null
和array
。 -
关联数组的使用应该遵循以下格式:
$config = [
'name' => 'Yii',
'options' => ['usePHP' => true],
];
- 更改现有变量的类型被看做是坏习惯,除非很有必要否则不要这么做。
public function save(Transaction $transaction, $argument2 = 100)
{
$transaction = new Connection; // bad
$argument2 = 200; // good
}
- 如果字符串中不包含变量和单引号,使用时用单引号。
$str = 'Like this.';
- 如果字符串中包含单引号,可以使用双引号去避免额外转义。
$str1 = "Hello $username!";
$str2 = "Hello {$username}!";
不允许这样替换:
$str3 = "Hello ${username}!";
连接字符串时的操作符左右加空格:
$name = 'Yii' . ' Framework';
- 如果字符串过长,使用以下格式:
$sql = "SELECT *"
. "FROM `post` "
. "WHERE `id` = 121 ";
使用 PHP 5.4 的短数组语法。
-
不可以
使用负数作数组的索引。 -
使用如下格式声明数组:
$arr = [3, 14, 15, 'Yii', 'Framework'];
- 如果太多数组元素在一行中:
$arr = [
3, 14, 15,
92, 6, $test,
'Yii', 'Framework',
];
关联数组的使用应该遵循以下格式:
$config = [
'name' => 'Yii',
'options' => ['usePHP' => true],
];
- 条件控制语句的括号前后 必须有一个空格。
- 括号里的运算符前后都应该有一个空格。
- 左大括号应该位于同一行。
- 右大括号应该位于新的一行。
- 始终用大括号包裹单行语句。
if ($event === null) {
return new Event();
} elseif ($event instanceof CoolEvent) {
return $event->instance();
} else {
return null;
}
//单行语句没有用大括号包裹,这是不允许的:
if (!$model && null === $event)
throw new Exception('test');
- 使用以下格式 switch:
switch ($this->phpType) {
case 'string':
$a = (string)$value;
break;
case 'integer':
case 'int':
$a = (integer)$value;
break;
case 'boolean':
$a = (boolean)$value;
break;
default:
$a = null;
}
doIt(2, 3);
doIt(['a' => 'b']);
doIt('a', [
'a' => 'b',
'c' => 'd',
]);
请注意 function
和 use
关键字与左括号之间的空格:
// 好的
$n = 100;
$sum = array_reduce($numbers, function ($r, $x) use ($n) {
$this->doMagic();
$r += $x * $n;
return $r;
});
// 糟糕的
$n = 100;
$mul = array_reduce($numbers, function($r, $x) use($n) {
$this->doMagic();
$r *= $x * $n;
return $r;
});
- 参考 PHPdoc 语法。
- 不允许没有文档注释的代码出现。
- 所有类文件 必须包含一个位于文件最上方的文件级别的文档块,以及一个位于类上方的类级别的文档块。
- 如果一个方法没有返回值,则没有必要使用
@return
。 - Yii2 中所有继承自
yii\base\Object
的虚拟属性都 必须 在文档块中添加一个@property
标签。标签的注释内容可以通过在 build 目录下运行./build php-doc
从相应的 getter 和 setter 方法的@return
和@param
标签中自动生成。如果生成的内容与@return
中不同,你可以向 getter 和 setter 方法添加@property
标签去显式的指明内容。
/**
* 返回所有属性或单个属性的错误信息
* @param string $attribute 属性名,使用 null 取回所有属性的错误信息。
* @property array 一个所有属性错误信息的数组,没有错误则返回空数组。
* 结果是一个二维数组,详细描述见 [[getErrors()]]。
* @return array 所有属性或指定属性的错误信息,没有错误则返回空数组。
* 请注意,当返回所有属性的错误信息时,结果是一个二维数组,格式是这样:
* ...
*/
public function getErrors($attribute = null)
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* Component 是一个提供了 *property*, *event* 和 *behavior* 的基类。
*
* @include @yii/doc/base-Component.md
*
* @author Qiang Xue <[email protected]>
* @since 2.0
*/
/**
* 返回一个事件的附加事件列表
* 你可以通过添加和删除处理去操作返回的 [[Vector]] 对象。
* 例如:
*
* ~~~
* $component->getEventHandlers($eventName)->insertAt(0, $eventHandler);
* ~~~
*
* @param string $name 事件名称
* @return Vector 该事件的附加事件处理列表
* @throw Exception 如果事件未定义
*/
public function getEventHandlers($name)
{
if (!isset($this->_e[$name])) {
$this->_e[$name] = new Vector;
}
$this->ensureBehaviors();
return $this->_e[$name];
}
正如上面所示, PHPDoc 文档块中可以使用 markdown 语法。
这里有一些额外需要掌握的语法,用以在文档中对类、方法和属性进行链接:
[[canSetProperty]]
将会创建一个链接,指向当前类中的canSetProperty
方法或属性。[[Component::canSetProperty]]
将会创建一个链接,指向同一个命名空间下Component
类中的canSetProperty
方法或属性。[[yii\base\Component::canSetProperty]]
将会创建一个链接,指向yii\base
命名空间下Component
类中的canSetProperty
方法或属性。[[Component]]
将会创建一个链接指向同一个命名空间下的Component
类。这里写上命名空间也无妨。
用下述方法定义链接的文字:
... as displayed in the [[header|header cell]].
|前面的内容是上述的指向方法、属性或类的链接地址, 后面的内容为链接文字。
也可以使用如下语法链接到权威指南:
[link to guide](guide:file-name.md)
[link to guide](guide:file-name.md#subsection)
- 单行注释应该使用
//
开头而不是#
。 - 单行注释应该自成一行。
必须 尽可能使用 empty()
。
当条件嵌套开始变得混乱应该尽早 return
。如果方法很短则无关紧要。
除了下述场景以外一律使用 static
。
- 访问类常量必须通过
self
, 例如self::MY_CONSTANT
。 - 访问私有静态属性必须通过
self
, 例如self::$_events
。 - 允许递归调用
self
去而不是继承该类。
设置一个组件不要做某事应该传的值为 false
,不应该假设为 null
, ''
或 []
。
- 使用小写。
- 使用名字的复数形式表示对象(例如Validators)。
- 使用单数形式表示相关的功能/特性(例如Web)。