PSR 是 PHP Standards Recommendation(PHP 推荐标准)的简称。如果最近读过关于 PHP 的博客,你或许见过 PSR-1、PSR-2 和 PSR-3 等术语。这些都是 PHP-FIG(PHP Framework Interop Group)制定的推荐规范。这些规范的名称以 PSR-
开头,后面跟着一个数字。PHP-FIG 制定的每个推荐规范用于解决大多数 PHP 框架经常会遇到的某个具体问题。PHP 框架无需频繁解决相同的问题,他们可以遵守 PHP-FIG 制定的推荐规范,使用共同的方案来解决。
和其他许多规范和标准一样,PHP-FIG 发布的这些推荐规范,可以说是现代 PHP 生态系统的牢固基石,定义了 PHP 组件和框架实现互操作性的方式。
目前,PHP-FIG 发布了五个推荐规范:
如果你数了,会发现只有四个推荐规范,:smile: 这是由于 PHP-FIG 废弃了第一份推荐规范 PSR-0,已被新发布的 PSR-4 替代了。
如果想编写符合社区标准的 PHP 代码,首先要遵守 PSR-1,这是最容易遵守的 PHP 标准,简单到你可能已经使用了。
符合 PSR-1 规范的代码必须满足以下要求:
只能使用 <?php
和 <?=
标签。
只能使用 UTF-8 无 BOM(Byte Order Mark) 字符集编码。
可以定义符号(类、函数和常量等),或者执行有副作用的操作(例如,输出结果和修改配置,写入数据库等对环境产生影响的操作),但不能同时做这两件事。
命名空间和类必须遵守 PSR-4 自动加载标准。
必须使用首字母大写的驼峰法命名,如 StudlyCaps
。
必须使用大写字母及下划线方式命名。
必须使用驼峰法命名,如 camelCase
。
贯彻 PSR-1 之后,下一步要实施 PSR-2,进一步定义 PHP 的代码风格。PSR-2 制定的代码风格对有多个来自世界各地的贡献者的 PHP 框架来说,可谓是及时雨。因为每个贡献者都有自己独特的风格和偏好,严格的统一代码风格能让开发者轻易地编写代码,而且其他贡献者能快速理解代码的作用。
符合 PSR-2 规范的代码必须满足以下要求:
必须遵守 PSR-1 代码规范。
必须用 4 个空格进行缩进,不能用 tab。PHP 关键字必须小写。用 Unix 风格的换行符(LF)。php 文件末尾省略 ?>
。
建议每行不超过 80 个字符,软件每行限制为 120 个字符。
命名空间声明语句 namespace
后必须换行,use
声明语句后必须换行。
类定义体起始符 {
必须新起一行,结束符 }
在末尾新起一行。
方法定义体起始符 {
必须新起一行,结束符 }
在末尾新起一行。
必须在所有属性和方法中声明可见性(即 public, protected, private);abstract
和 final
必须在其之前声明。static
必须在其之后声明。
控制结构关键字后面必须有一个空格,包括:if、elseif、else、switch、case、while、do while、for、foreach、try 和 catch。方法和函数后面不能有空格。
控制结构起始符 {
必须在同一行,结束符 }
在末尾新起一行。
控制结构起始括号 (
后不能有空格,结束括号 )
前不能有空格。参数之间用逗号隔开,逗号后跟一个空格。
日志记录接口规定必须实现九个方法:
namespace Psr\Log;
/**
* Describes a logger instance
*
* The message MUST be a string or object implementing __toString().
*
* The message MAY contain placeholders in the form: {foo} where foo
* will be replaced by the context data in key "foo".
*
* The context array can contain arbitrary data, the only assumption that
* can be made by implementors is that if an Exception instance is given
* to produce a stack trace, it MUST be in a key named "exception".
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
* for the full interface specification.
*/
interface LoggerInterface
{
/**
* System is unusable.
*
* @param string $message
* @param array $context
* @return null
*/
public function emergency($message, array $context = array());
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
* @return null
*/
public function alert($message, array $context = array());
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
* @return null
*/
public function critical($message, array $context = array());
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
* @param array $context
* @return null
*/
public function error($message, array $context = array());
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
* @return null
*/
public function warning($message, array $context = array());
/**
* Normal but significant events.
*
* @param string $message
* @param array $context
* @return null
*/
public function notice($message, array $context = array());
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
* @return null
*/
public function info($message, array $context = array());
/**
* Detailed debug information.
*
* @param string $message
* @param array $context
* @return null
*/
public function debug($message, array $context = array());
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
* @param array $context
* @return null
*/
public function log($level, $message, array $context = array());
}
把命名空间的前缀和文件系统中的目录对应起来。好处在于,使用遵循这一规范的类,可以很轻松实现自动加载,而不需要在每个文件里面引入。比如使用 Composer 自动生成的 PSR-4 自动加载,只需要在入口文件引入 autoload.php
即可实现自动加载。
举例来说:
完整命名空间 | 命名空间前缀 | 基本目录 | 最终文件路径 |
---|---|---|---|
\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 |