文件
- PHP 文件 必须 且只可使用
不带BOM的UTF-8
编码。 - PHP 代码 必须 使用
<?php ?>
长标签 或<?= ?>
短输出标签; - PHP 文件 必须 省略最后的
?>
结束标签。 - PHP 文件 必须 以一个空白行作为结束。
- PHP 文件 必须 使用
Unix LF (linefeed)
作为行的结束符。 - PHP 文件 应该 要不就只定义新的声明,如类、函数或常量等不产生
副作用
的操作,要不就只书写会产生副作用
的逻辑操作,但 不该 同时具有两者。
副作用
包含却不仅限于:- 生成输出
- 直接的
require
或include
- 连接外部服务
- 修改 ini 配置
- 抛出错误或异常
- 修改全局或静态变量
- 读或写文件等
行
- 行的长度 一定不可 有硬性的约束,软性的长度约束 必须 要限制在 120 个字符以内;每行 不该 多于 80 个字符,大于 80 字符的行 应该 折成多行。
- 非空行后 一定不可 有多余的空格符。
- 空行 可以 使得阅读代码更加方便以及有助于代码的分块。
- 每行 一定不可 存在多于一条语句。
- 代码 必须 使用 4 个空格符的缩进,一定不可 用
tab
键。
关键字 以及 True/False/Null
- PHP 所有 关键字 必须 全部小写。
- 常量
true
、false
和null
也 必须 全部小写。
namespace 以及 use 声明
namespace
声明后 必须 插入一个空白行。- 所有
use
必须 在namespace
后声明。 - 每条
use
声明语句 必须 只有一个use
关键词。 use
声明语句块后 必须 要有一个空白行。
<?php
namespace Vendor\Package;
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
// ... 更多的 PHP 代码在这里 ...
类的命名
此处的「类」泛指所有的「Class 类」、「接口」、「traits 可复用代码块」以及其它类似结构。
- 每个类都独立为一个文件。
- 一个完整的类名需具有以下结构:
\<命名空间>(\<子命名空间>)*\<类名>
- 完整的类名 必须 要有一个顶级命名空间,被称为 “vendor namespace”;
- 完整的类名 可以 有一个或多个子命名空间;
- 完整的类名 必须 有一个最终的类名;
- 完整的类名中任意一部分中的下滑线都是没有特殊含义的;
- 完整的类名 可以 由任意大小写字母组成;
- 所有类名都 必须 是大小写敏感的。
- 类的命名 必须 遵循
StudlyCaps
大写开头的驼峰命名规范。
- PHP 5.3 及以后版本的代码 必须 使用正式的命名空间。(5.2.x 及之前的版本 应该 使用伪命名空间的写法,约定俗成使用顶级的组织名称(vendor name)如 Vendor_ 为类前缀)
<?php
// 5.2.x及之前版本的写法
class Vendor_Model_Foo
{
}
类的自动加载
- 完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为「命名空间前缀」,其 必须 与至少一个「文件基目录」相对应;
- 紧接命名空间前缀后的子命名空间 必须 与相应的「文件基目录」相匹配,其中的命名空间分隔符将作为目录分隔符。
- 末尾的类名 必须 与对应的以 .php 为后缀的文件同名。
- 自动加载器(autoloader)的实现 一定不可 抛出异常、一定不可 触发任一级别的错误信息以及 不应该 有返回值。
完整类名 | 命名空间前缀 | 文件基目录 | 文件路径 |
---|---|---|---|
\Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
\Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
\Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
\Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |
类的扩展与继承
- 关键词
extends
和implements
必须 写在类名称的同一行。 - 类的开始花括号 必须 独占一行,结束花括号也 必须 在类主体后独占一行。
class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
// 这里面是常量、属性、类方法
}
- implements 的继承列表也 可以 分成多行,这样的话,每个继承接口名称都 必须 分开独立成行,包括第一个。
class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// 这里面是常量、属性、类方法
}
类的常量
类的常量中所有字母都 必须 大写,单词间以下划线分隔。
<?php
namespace Vendor\Model;
class Foo
{
const VERSION = '1.0';
const DATE_APPROVED = '2012-06-01';
}
类的属性
- 每个属性都 必须 添加访问修饰符。
- 一定不可 使用关键字
var
声明一个属性。 - 每条语句 一定不可 定义超过一个属性。
- 不该 使用下划线作为前缀,来区分属性是
protected
或private
。 - 类的属性命名 可以 遵循(不做强制要求,但无论遵循哪种命名方式,都 应该 在一定的范围内保持一致。这个范围可以是整个团队、整个包、整个类或整个方法):
- 大写开头的驼峰式 (
$StudlyCaps
) - 小写开头的驼峰式 (
$camelCase
) - 下划线分隔式 (
$under_score
)
- 大写开头的驼峰式 (
<?php
namespace Vendor\Package;
class ClassName
{
public $foo = null;
}
类的方法
- 所有方法都 必须 添加访问修饰符。
- 不该 使用下划线作为前缀,来区分方法是
protected
或private
。 - 方法名称后 一定不可 有空格符,其开始花括号 必须 独占一行,结束花括号也 必须 在方法主体后单独成一行。
- 方法名称 必须 符合
camelCase()
式的小写开头驼峰命名规范。
<?php
namespace Vendor\Package;
class ClassName
{
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// method body
}
}
方法的参数
- 参数列表中,每个逗号后面 必须 要有一个空格,而逗号前面 一定不可 有空格。
- 有默认值的参数,必须 放到参数列表的末尾
- 参数列表 可以 分列成多行,这样,包括第一个参数在内的每个参数都 必须 单独成行。
- 拆分成多行的参数列表后,结束括号以及方法开始花括号 必须 写在同一行,中间用一个空格分隔
<?php
namespace Vendor\Package;
class ClassName
{
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// method body
}
}
修饰符
需要添加 abstract
或 final
声明时,必须 写在访问修饰符前,而 static
则 必须 写在访问修饰符后
<?php
namespace Vendor\Package;
abstract class ClassName
{
protected static $foo;
abstract protected function zim();
final public static function bar()
{
// method body
}
}
方法及函数调用
- 方法及函数调用时,方法名或函数名与参数左括号之间 一定不可 有空格,参数右括号前也 一定不可 有空格。
参数列表中,每个逗号后面 必须 要有一个空格,而逗号前面 一定不可 有空格。
<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);
参数 可以 分列成多行,此时包括第一个参数在内的每个参数都 必须 单独成行。
<?php
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);
控制结构
- 控制结构关键词后 必须 有一个空格。
- 左括号
(
后 一定不可 有空格。 - 右括号
)
前也 一定不可 有空格。 - 右括号
)
与开始花括号{
间 必须 有一个空格。 - 结构体主体 必须 要有一次缩进。
- 结束花括号
}
必须 在结构体主体后单独成行。 - 每个结构体的主体都 必须 被包含在成对的花括号之中,这能让结构体更加结构化,以及减少加入新行时,出错的可能性。
if 、elseif 和 else
- 应该 使用关键词
elseif
代替所有else if
else
和elseif
都与前面的结束花括号在同一行。
<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body;
}
switch 和 case
case
语句 必须 相对switch
进行一次缩进,而break
语句以及case
内的其它语句都 必须 相对case
进行一次缩进。- 如果存在非空的
case
直穿语句,主体里 必须 有类似// no break
的注释。
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}
while 和 do while
<?php
while ($expr) {
// structure body
}
<?php
do {
// structure body;
} while ($expr);
for
<?php
for ($i = 0; $i < 10; $i++) {
// for body
}
foreach
<?php
foreach ($iterable as $key => $value) {
// foreach body
}
try, catch
<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}
闭包
- 闭包声明时,关键词
function
后以及关键词use
的前后都 必须 要有一个空格。 - 开始花括号 必须 写在声明的同一行,结束花括号 必须 紧跟主体结束的下一行。
- 参数列表和变量列表的左括号后以及右括号前,一定不可 有空格。
- 参数列表和变量列表中,逗号前 一定不可 有空格,而逗号后 必须 要有空格。
- 闭包中有默认值的参数 必须 放到列表的后面。
- 参数列表以及变量列表 可以 分成多行,这样,包括第一个在内的每个参数或变量都 必须 单独成行,而列表的右括号与闭包的开始花括号 必须 放在同一行。
- 闭包被直接用作函数或方法调用的参数时,以上规则仍然适用
<?php
$closureWithArgs = function ($arg1, $arg2) {
// body
};
$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
// body
};
<?php
$longArgs_noVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) {
// body
};
$noArgs_longVars = function () use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};
$longArgs_longVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};
$longArgs_shortVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use ($var1) {
// body
};
$shortArgs_longVars = function ($arg) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};
<?php
$foo->bar(
$arg1,
function ($arg2) use ($var1) {
// body
},
$arg3
);
本文根据 PHP标准规范 的PSR-1,PSR-2,PSR-4整理汇总