PSR 是 PHP Standard Recommendations 的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准。
基础编码规范 PSR-1
PHP代码文件 必须 以
不带 BOM
的UTF-8
编码;类的命名 必须 遵循
StudlyCaps
大写开头的驼峰命名规范;类中的
常量所有字母
都 必须 大写,单词间用下划线分隔;方法名称 必须 符合
camelCase
式的小写开头驼峰命名规范。一份 PHP 文件中
应该
要不就只定义新的声明,如类、函数或常量等不产生副作用
的操作,要不就只书写会产生副作用
的逻辑操作,但不该
同时具有两者。
反例:
<?php
// 「副作用」:修改 ini 配置
ini_set('error_reporting', E_ALL);
// 「副作用」:引入文件
include "file.php";
// 「副作用」:生成输出
echo "<html>\n";
// 声明函数
function foo()
{
// 函数主体部分
}
编码风格规范 PSR-2
所有PHP文件 必须 以一个空白行作为结束。
代码 必须 使用
4个空格符
的缩进,一定不可 用tab键
。PHP所有
关键字
必须 全部小写
。常量true
、false
和null
也 必须 全部小写。关键词 extends 和 implements 必须 写在类名称的同一行。
类的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。
方法的开始花括号({) 必须 写在函数声明后自成一行,结束花括号(})也 必须 写在函数主体后自成一行。
类的属性和方法 必须 添加访问修饰符(
private
、protected
以及public
),abstract
以及final
必须 声明在访问修饰符之前,而static
必须 声明在访问修饰符之后。所有方法都 必须 添加访问修饰符。
方法的参数, 有默认值的参数,必须 放到参数列表的末尾。
示例:
<?php
namespace Vendor\Package;
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
class Foo extends Bar implements FooInterface
{
public function sampleFunction($a, $b = null)
{
if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}
}
final public static function bar()
{
// 方法的内容
}
}
日志接口规范
- LoggerInterface 接口对外定义了八个方法,分别用来记录 RFC 5424 中定义的八个等级的日志:debug、 info、 notice、 warning、 error、 critical、 alert 以及 emergency
- 记录信息参数 可以 携带占位符,实现者 可以 根据上下文将其它替换成相应的值。
- 每个记录函数都接受一个上下文数组参数,用来装载字符串类型无法表示的信息。 一定不可 抛出异常,或产生PHP出错、警告或提醒信息(error、warning、notice)。
- 如需通过上下文参数传入了一个 Exception 对象,必须 以 exception 作为键名。
<?php
/**
* 用上下文信息替换记录信息中的占位符
*/
function interpolate($message, array $context = array())
{
// 构建一个花括号包含的键名的替换数组
$replace = array();
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}
// 替换记录信息中的占位符,最后返回修改后的记录信息。
return strtr($message, $replace);
}
// 含有带花括号占位符的记录信息。
$message = "User {username} created";
// 带有替换信息的上下文数组,键名为占位符名称,键值为替换值。
$context = array('username' => 'bolivar');
// 输出 "Username bolivar created"
echo interpolate($message, $context);
<?php
namespace Psr\Log;
/**
* 日志记录实例
*
* 日志信息变量 —— message,**必须** 是一个字符串或是实现了 __toString() 方法的对象。
*
* 日志信息变量中 **可以** 包含格式如 “{foo}” (代表 foo) 的占位符,
* 它将会由上下文数组中键名为「foo」的键值替代。
*
* 上下文数组可以携带任意的数据,唯一的限制是,当它携带的是一个 exception 对象时,它的键名 **必须** 是 "exception"。
*
* 详情可参阅: https://github.com/PizzaLiu/PHP-FIG/blob/master/PSR-3-logger-interface-cn.md
*/
interface LoggerInterface
{
/**
* 系统不可用
*
* @param string $message
* @param array $context
* @return null
*/
public function emergency($message, array $context = array());
/**
* **必须** 立刻采取行动
*
* 例如:在整个网站都垮掉了、数据库不可用了或者其他的情况下, `应该` 发送一条警报短信把你叫醒。
*
* @param string $message
* @param array $context
* @return null
*/
public function alert($message, array $context = array());
/**
* 紧急情况
*
* 例如:程序组件不可用或者出现非预期的异常。
*
* @param string $message
* @param array $context
* @return null
*/
public function critical($message, array $context = array());
/**
* 运行时出现的错误,不需要立刻采取行动,但必须记录下来以备检测。
*
* @param string $message
* @param array $context
* @return null
*/
public function error($message, array $context = array());
/**
* 出现非错误性的异常。
*
* 例如:使用了被弃用的API、错误地使用了API或者非预想的不必要错误。
*
* @param string $message
* @param array $context
* @return null
*/
public function warning($message, array $context = array());
/**
* 一般性重要的事件。
*
* @param string $message
* @param array $context
* @return null
*/
public function notice($message, array $context = array());
/**
* 重要事件
*
* 例如:用户登录和SQL记录。
*
* @param string $message
* @param array $context
* @return null
*/
public function info($message, array $context = array());
/**
* debug 详情
*
* @param string $message
* @param array $context
* @return null
*/
public function debug($message, array $context = array());
/**
* 任意等级的日志记录
*
* @param mixed $level
* @param string $message
* @param array $context
* @return null
*/
public function log($level, $message, array $context = array());
}
缓存接口规范
- 所有存进实现类库的数据,都 必须 能做到原封不动的取出。
- 实在无法「完整取出」存入的数据的话,实现类库 必须 把「缓存丢失」标示作为返回,而不是损坏了的数据。
- 缓存系统里的错误 一定不可 导致应用程序故障
<?php
namespace Psr\Cache;
/**
* CacheItemInterface 定了缓存系统里对缓存项操作的接口
*/
interface CacheItemInterface
{
/**
* 返回当前缓存项的「键」
*
* 「键」由实现类库来加载,并且高层的调用者(如:CacheItemPoolInterface)
* `应该` 能使用此方法来获取到「键」的信息。
*
* @return string
* 当前缓存项的「键」
*/
public function getKey();
/**
* 凭借此缓存项的「键」从缓存系统里面取出缓存项。
*
* 取出的数据 **必须** 跟使用 `set()` 存进去的数据是一模一样的。
*
* 如果 `isHit()` 返回 false 的话,此方法必须返回 `null`,需要注意的是 `null`
* 本来就是一个合法的缓存数据,所以你 `应该` 使用 `isHit()` 方法来辨别到底是
* "返回 null 数据" 还是 "缓存里没有此数据"。
*
* @return mixed
* 此缓存项的「键」对应的「值」,如果找不到的话,返回 `null`
*/
public function get();
/**
* 确认缓存项的检查是否命中。
*
* 注意: 调用此方法和调用 `get()` 时 **一定不可** 有先后顺序之分。
*
* @return bool
* 如果缓冲池里有命中的话,返回 `true`,反之返回 `false`
*/
public function isHit();
/**
* 为此缓存项设置「值」。
*
* 参数 $value 可以是所有能被 PHP 序列化的数据,序列化的逻辑
* 需要在实现类库里书写。
*
* @param mixed $value
* 将被存储的可序列化的数据。
*
* @return static
* 返回当前对象。
*/
public function set($value);
/**
* 设置缓存项的准确过期时间点。
*
* @param \DateTimeInterface $expiration
*
* 过期的准确时间点,过了这个时间点后,缓存项就 **必须** 被认为是过期了的。
* 如果明确的传参 `null` 的话,**可以** 使用一个默认的时间。
* 如果没有设置的话,缓存 `应该` 存储到底层实现的最大允许时间。
*
* @return static
* 返回当前对象。
*/
public function expiresAt($expiration);
/**
* 设置缓存项的过期时间。
*
* @param int|\DateInterval $time
* 以秒为单位的过期时长,过了这段时间后,缓存项就 **必须** 被认为是过期了的。
* 如果明确的传参 `null` 的话,**可以** 使用一个默认的时间。
* 如果没有设置的话,缓存 `应该` 存储到底层实现的最大允许时间。
*
* @return static
* 返回当前对象
*/
public function expiresAfter($time);
}
<?php
namespace Psr\Cache;
/**
* CacheItemPoolInterface 生成 CacheItemInterface 对象
*/
interface CacheItemPoolInterface
{
/**
* 返回「键」对应的一个缓存项。
*
* 此方法 **必须** 返回一个 CacheItemInterface 对象,即使是找不到对应的缓存项
* 也 **一定不可** 返回 `null`。
*
* @param string $key
* 用来搜索缓存项的「键」。
*
* @throws InvalidArgumentException
* 如果 $key 不是合法的值,\Psr\Cache\InvalidArgumentException 异常会被抛出。
*
* @return CacheItemInterface
* 对应的缓存项。
*/
public function getItem($key);
/**
* 返回一个可供遍历的缓存项集合。
*
* @param array $keys
* 由一个或者多个「键」组成的数组。
*
* @throws InvalidArgumentException
* 如果 $keys 里面有哪个「键」不是合法,\Psr\Cache\InvalidArgumentException 异常
* 会被抛出。
*
* @return array|\Traversable
* 返回一个可供遍历的缓存项集合,集合里每个元素的标识符由「键」组成,即使即使是找不到对
* 的缓存项,也要返回一个「CacheItemInterface」对象到对应的「键」中。
* 如果传参的数组为空,也需要返回一个空的可遍历的集合。
*/
public function getItems(array $keys = array());
/**
* 检查缓存系统中是否有「键」对应的缓存项。
*
* 注意: 此方法应该调用 `CacheItemInterface::isHit()` 来做检查操作,而不是
* `CacheItemInterface::get()`
*
* @param string $key
* 用来搜索缓存项的「键」。
*
* @throws InvalidArgumentException
* 如果 $key 不是合法的值,\Psr\Cache\InvalidArgumentException 异常会被抛出。
*
* @return bool
* 如果存在「键」对应的缓存项即返回 true,否则 false
*/
public function hasItem($key);
/**
* 清空缓冲池
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function clear();
/**
* 从缓冲池里移除某个缓存项
*
* @param string $key
* 用来搜索缓存项的「键」。
*
* @throws InvalidArgumentException
* 如果 $key 不是合法的值,\Psr\Cache\InvalidArgumentException 异常会被抛出。
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function deleteItem($key);
/**
* 从缓冲池里移除多个缓存项
*
* @param array $keys
* 由一个或者多个「键」组成的数组。
*
* @throws InvalidArgumentException
* 如果 $keys 里面有哪个「键」不是合法,\Psr\Cache\InvalidArgumentException 异常
* 会被抛出。
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function deleteItems(array $keys);
/**
* 立刻为「CacheItemInterface」对象做数据持久化。
*
* @param CacheItemInterface $item
* 将要被存储的缓存项
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function save(CacheItemInterface $item);
/**
* 稍后为「CacheItemInterface」对象做数据持久化。
*
* @param CacheItemInterface $item
* 将要被存储的缓存项
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function saveDeferred(CacheItemInterface $item);
/**
* 提交所有的正在队列里等待的请求到数据持久层,配合 `saveDeferred()` 使用
*
* @return bool
* 成功返回 true,有错误发生返回 false
*/
public function commit();
}
参考文档
- 代码风格指南
- PHP 标准规范
- 「PSR 规范」PSR-1 基础编码规范
- 「PSR 规范」PSR-2 编码风格规范
- 「PSR 规范」PSR-3 日志接口规范
- 「PSR 规范」PSR-4 自动加载规范
- 「PSR 规范」PSR-6 缓存接口规范