-
Notifications
You must be signed in to change notification settings - Fork 3
Description
PHP 标准规范
PSR: 是 PHP Standard Recommendations 缩写,有 PHP FIG 组织指定的PHP 开发实践规范。
PHP FIG: 是 Framework Interoperablility Group(框架可互用性小组)缩写,于 2009 年由几位开源框架开发者成立。
目前已通过表决六套方案,并得到大部分 PHP 框架的支持和认可。
一 基础编码规范
1.1 名词解释
- 必须(MUST): 绝对,严格无条件遵守
- 一定不要(MUST NOT): 严格禁止
- 应该(SHOULD): 强烈建议这样做,但不强求
- 不应该(SHOULD NOT):强烈不建议这样做,但不强求
- 可以(MAY)和 可选(OPTIONAL): 选择性高一点
1.2 文件
1.2.1 PHP 标签
必须 使用 长标签 或 <?= > 短标签,一定不可 使用任何自定义标签
1.2.2 PHP 字符编码
PHP 文件必须 采用 无 BOM 的 UTF-8 字符编码
1.2.3 副作用
一个 PHP 文件 应该
- 要么定义类声明,如类、函数、常量等不产生副作用的操作
- 要么仅书写产生副作用的逻辑操作
不能兼而有之。
「副作用」是什么?
仅通过包含文件而执行的逻辑操作(不需要直接声明类、函数和常量)
「副作用」种类说明
- 生成输出
echo ""; - 直接
require或include - 设置 ini 配置
ini_set("error_reporting", E_ALL); - 连接外部服务
- 抛出错误或异常
- 修改全局或静态变量
- 读或写文件
产生副作用编码示例
<?php
// 「副作用」: 修改 ini 配置
ini_set("error_reporting", E_ALL);
// 「副作用」: 引入文件
include "filename.php";
// 「副作用」:生成输出
echo "<html></html>";
//声明函数
function foo()
{
}不产生「副作用」的代码
<?php
//声明函数
function foo()
{
}
// 条件声明 不 属于「副作用」
if (! function_exists("bar") )
{
function bar()
{
}
}1.3 命名空间与类
命名空间与类必须遵循 PSR-4 标准: 自动加载规范
- 每个类必须使用独立的文件
- 命名空间至少有一个层级,顶级层级是组织名称(Vendor name)
- 必须使用
StudlyCaps首字母大写的驼峰命名规范 - PHP 5.3 之后 必须 使用正式的命名空间
- PHP 5.2.x 及一下版本 应该 使用伪命名空间的写法,约定俗成使用的顶级的组织名称(Vendor name)如
Vendor_为类前缀
示例:
<?php
// PHP 5.3 及以后版本类命名
namespace Vendor\Model;
class Foo
{
}<?php
// PHP 5.2.x 及以前版命名空间使用
class Vendor_Model_Foo
{
}1.4 类的常量、属性和方法
类:指类、接口或可复用的代码块traits
1.4.1 常量
全部字母 必须 使用大写,单词以下划线分隔
1.4.2 属性
属性可以遵循:
- 首字母大写的驼峰命名
$StudlyCaps - 首字母小写的驼峰命名
$studlyCpas - 下划线分隔
$under_score
1.4.3 方法
必须 符合 camelCase() 首字母小写的驼峰命名规范
二 编码风格规范
编码风格规范是对基础编码规范的继承和扩展
2 个示例看规范
示例1:
<?php
namespace Vendor\Model;
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherModel\BazClass;
/**
* 编码风格规范:
* 1. 文件 **必须** 以一个空白行结尾
* 2. PHP 文件 **必须** 省略结束标签 **?>**
* 3. 一行代码 **必须** 限制在 120 个字符以内,**不应该** 超过 80 个字符
* 如果超过,**应该** 拆分成多行
* 4. PHP 所有 **关键词** 及 常量 true/false/null **必须**小写;关键词包括但不限于 private, public,
* class, final, static 等
* 5. namespace 声明完成后 **必须** 插入空白行,如本文第 151 行即示例第 3 行
* 6. use **必须** 在 namespace 声明后
* 7. 每条 use **必须** 有且只有一个 use 关键词
* 9. use 声明块后 **必须** 有一个空行,如本文第 155 行即示例第 7 行
* 10. extends 及 implements 关键词 **必须** 卸载类名称的同一行
* 11. 类开始 { 及结束花括号 } **必须** 独占一行
*/
class Foo extends Bar implements FooInterface
{
/**
* 12. 所有 方法 和 属性 **必须** 添加访问修饰符:private, protected, public
* 13. **一定不可** 使用关键词 **var** 声明属性
* 14. 每条语句 **一定不可** 定义超过一个属性
* 15. **不该** 使用下划线作为前缀,区分 protected 或 private
*/
private $name = '';
// 参见 13
// var $age = 18;
// 参见 14
// private $email;private $address;
// 参见 15
// private $_phone;
/**
* 16. 方法名后 **一定不可** 有空格。如:sampleFunction($a, $b = null)
* 17. 方法的开始花括号 { 和结束花括号 } **必须** 独占一行
* 18. 参数左括号 ( 之后与右括号 ) 之前 **一定不可** 有空格
* 19. 有默认值的参数 **必须** 放在参数列表结尾。如:$b
* 20. 参数列表中每个逗号之后 **必须** 有一个空格,逗号之前 **一定不可以有空格**
*/
public function sampleFunction($a, $b = null)
{
}
/**
* 21. 参数列表 **可以** 分列多行,包括第一个参数在内的所有参数 **必须** 单独成行
* 22. 拆分为多行的参数列表的方法的结束括号 ) 和方法开始花括号 { **必须**卸载同一行,中间用空格分隔
*/
public function multipleSampleFunction(
$a,
$b = null
) {
}
/**
* 23. abstract, final 声明时,**必须** 写在访问操作符前
* 24. static 关键词 **必须** 写在访问操作符之后
*/
final public static function bar($a, $b = null)
{
/**
* 25. 方法及函数调用是,方法名或函数名与参数左括号 ( 之间 **一定不可** 有空格
* 26. 调用是参数可以分列多行,包括第一个参数在内的每个参数 **必须** 单独成行
* 27. 控制结构关键词后 **必须** 有一个空格。如 if (
* 28. 控制结构左括号 ( 之后及右括号 ) 之前 **一定不可** 有空格
* 29. 控制结构 右括号 ) 与 方法左花括号 { 之间 **必须** 有一个空格。如 ) {
* 30. 结构体 **必须** 有缩进
* 31. 缩进 **必须** 使用 4 个空格符,而不是 「Tab 键」缩进
* 32. 方法右括号 } **必须** 单独成行
* 33. else if **应当** 替换为 elseif ,这样关键词都像单独的一个词
*/
if ($a == $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar(
$arg2,
$arg3
);
}
}
}示例2:
<?php
namespace Vendor\Package;
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
/**
* 34. implements 的继承列表也 **可以** 拆分称多行,但包括第一个在内的每个集成接口都 **必须** 单独成行
*/
class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// 这里面是常量、属性、类方法
}三 日志接口规范
日志接口规范,定义了日志类库通用接口规范,如有日志记录需求的可以通过集成 Pst\Log\LoggerInterface 来记录日志信息
日志错误级别
- debug: 详细调试信息
- info: 关注的事件信息。示例:用户登录日志,SQL 语句日志
- notice: 常见的消息事件
- warning: 非致命错误的警告。示例: 弃用或不建议使用的 API
- error: 运行时错误,不需要立即解决但是应该记录到日志
- critical: 必要条件错误。示例:项目运行必要组件,或未知异常。
- alert: 必须立即修复的错误,需要发送一个 SMS信息。示例:站点宕机,数据库无法连接等。
- emergency: 紧急错误,系统不可用
接口方法
LoggerInterface 提供以上 8 个错误等级对应的日志接口
此外还提供 log() 方法,该方法第一个参数为日志错误级别标识,调用该方法结果 必须 与单独使用错误等级对应的方法结果相同
使用 monolog 日志库
TODO monolog: 是一款 PHP 符合 PSR 规范开发的日志记录库,可以将日志内容记录到 files(文件), sockets(套接字接口),inboxes(消息系统), databases(数据库)和 various web services (各种 web 服务)。
【翻译】Monolog使用说明 - 即Monolog中文文档
自动加载规范
自动加载规范是对 TODO PHP 官方自动加载相关类 的规范
详细说明
- 此处的「类」泛指所有的「Class类」、「接口」、「traits 可复用代码块」以及其它类似结构。
- 一个完整的类名需具有以下结构:
<code>\<命名空间>(\<子命名空间>)*\<类名></code>
- 完整的类名 必须 要有一个顶级命名空间,被称为 "vendor namespace";
- 完整的类名 可以 有一个或多个子命名空间;
- 完整的类名 必须 有一个最终的类名;
- 完整的类名中任意一部分中的下滑线都是没有特殊含义的;
- 完整的类名 可以 由任意大小写字母组成;
- 所有类名都 必须 是大小写敏感的。
- 当根据完整的类名载入相应的文件
- 完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为「命名空间前缀」,其必须与至少一个「文件基目录」相对应;
- 紧接命名空间前缀后的子命名空间 必须 与相应的「文件基目录」相匹配,其中的命名空间分隔符将作为目录分隔符。
- 末尾的类名 必须 与对应的以 .php 为后缀的文件同名。
- 自动加载器(autoloader)的实现 一定不可 抛出异常、一定不可 触发任一级别的错误信息以及 不应该 有返回值。
缓存接口规范
目标
现在每个框架基本都有专属的功能多样的缓存库,但是这些库都有自己的实现 API,开发者在使用过程中都不得不学习每个框架的 API 接口。
缓存接口的目标:创建一套通用的接口规范,能够让开发人员整合到现有框架和系统,而不需要去 开发框架专属的适配器类
定义
-
调用类库
调用者,使用缓存服务的类库,调用对象是本缓存接口规范的具体「实现类库」 -
实现类库
是「本缓存接口规范的」具体实现,实现类库必须实现 Cache\CacheItemPoolInterface 和 Cache\CacheItemInterface 接口
- 生存时间(TTL: Time To Live)
定义缓存存活时间,以秒为单位
- 过期时间
定义准确的过期时间点,通常为缓存存储时间点加上 TTL 时间值;
也可以是具体的 DateTime 对象
- 键(key)
长度为 1 的字符串,作为缓存项的唯一标识符。
键 必须 是:
A-Z, a-z, 0-9, _, . 的任意顺序的 UTF-8 编码,且长度小于 64 位
- 命中(Hit)
指在缓存系统中,调用类库使用「键」能够查找到对应的缓存项
调用类库应该先验证 isHit() 有命中后调用 get() 获取数据
- 未命中(Miss)
「命中」的反义
- 延迟(Dererred)
一个延迟的缓存,指的是这个缓存项可能不会立刻被存储到物理缓存池里
数据
实现类库 必须 支持所有 PHP 可序列化数据类型:
- String
- Integer
- Float
- Boolean
- Null
- Array
- Object
且反序列化结果 必须 与原数据完全一致
主要概念
- 缓存池 Pool
缓存池包含缓存系统里所有缓存数据的集合
- 缓存项 Items
一条缓存项在缓存池里代表了一对「键/值」对应的数据,「键」被视为每一个缓存项主键,是缓存项的 唯一标识符,必须 是不可变更的,当然,「值」可以 任意变更
- 错误处理