PHP PSR代码编写标准 作者: Chuwen 时间: 2017-06-04 分类: PHP,神奇技巧 #PHP PSR代码标准 PSR-0 自动加载规范 ========== 下面描述了关于自动加载器特性强制性要求: 强制性 --------- * 一个完全标准的命名空间必须要有以下的格式结构`\\(\)*` * 命名空间必须有一个顶级的组织名称 ("Vendor Name"). * 命名空间中可以根据情况使用任意数量的子空间 * 从文件系统中加载源文件的时,命名空间中的分隔符将被映射为 `DIRECTORY_SEPARATOR` * 命名空间中的类名中的`_`没有特殊含义,也将被作为`DIRECTORY_SEPARATOR`对待. * 标准的命名空间和类从文件系统加载源文件时只需要加上`.php`后缀即可 * 组织名,空间名,类名都可以随意使用大小写英文字符的组合 示例 -------- * `\Doctrine\Common\IsolatedClassLoader` => `/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php` * `\Symfony\Core\Request` => `/path/to/project/lib/vendor/Symfony/Core/Request.php` * `\Zend\Acl` => `/path/to/project/lib/vendor/Zend/Acl.php` * `\Zend\Mail\Message` => `/path/to/project/lib/vendor/Zend/Mail/Message.php` 命名空间和类名中的下划线 ----------------------------------------- * `\namespace\package\Class_Name` => `/path/to/project/lib/vendor/namespace/package/Class/Name.php` * `\namespace\package_name\Class_Name` => `/path/to/project/lib/vendor/namespace/package_name/Class/Name.php` 以上是我们为轻松实现自动加载特性设定的最低标准。你可以利用下面这个可以自动加载 PHP 5.3 类的SplClassLoader来测试你的代码是否符合以上这些标准。 实例 ---------------------- 下面是一个函数实例简单展示如何使用上面建议的标准进行自动加载 ``` `或者短输出式`= ?>`标签;它`不可`使用其他的标签变种。 ### 2.2. 字符编码 PHP代码`必须`只使用不带BOM的UTF-8。 ### 2.3. 副作用 一个文件`应当`声明新符号 (类名,函数名,常量等)并且不产生副作用,或者`应当`执行有副作用的逻辑,但不能同时做这两件事。 短语"副作用"意思是不直接执行逻辑的类,函数,常量等 *仅包括文件* “副作用”包含但不局限于:生成输出,显式地使用`require`或`include`,连接外部服务,修改ini配置,触发错误或异常,修改全局或者静态变量,读取或修改文件等等 下面是一个既包含声明又有副作用的示例文件;即应避免的例子: ``` \n"; // declaration function foo() { // function body } ``` 下面是一个仅包含声明的示例文件;即需要提倡的例子: ``` $b) { $foo->bar($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } } ``` 2. 概括 ---------- ### 2.1 基础代码规范 代码`必须`遵守 [PSR-1][] 的所有规则。 ### 2.2 文件 所有的PHP文件`必须`使用Unix LF(换行)作为行结束符。 所有PHP文件`必须`以一个空行结束。 纯PHP代码的文件关闭标签`?>``必须`省略 ### 2.3. 行 行长度`不可`有硬限制。 行长度的软限制`必须`是120个字符;对于软限制,自动样式检查器`必须`警告但`不可`报错。 行实际长度`不应`超过80个字符;较长的行`应当`被拆分成多个不超过80个字符的后续行。 在非空行后面`不可`有空格。 空行`可以`用来改善可读性和区分相关的代码块。 一行`不应`多于一个语句。 ### 2.4. 缩进 代码`必须`使用4个空格的缩进,并且`不可`使用制表符作为缩进。 > 注意:只用空格,不和制表符混合使用,将会对避免代码差异,补丁,历史和注解中的一些问题有帮助。使用空格还可以使调整细微的缩进来改进行间对齐变得非常简单。 ### 2.5. 关键词和 True/False/Null PHP [keywords][] `必须`使用小写。 PHP常量`true`, `false`和`null``必须`使用小写。 [keywords]: http://php.net/manual/en/reserved.keywords.php 3. Namespace和Use声明 --------------------------------- 如果存在,`namespace`声明之后`必须`有一个空行。 如果存在,所有的`use`声明`必须`放在`namespace`声明的下面。 一个`use`关键字`必须`只用于一个声明。 在`use`声明代码块后面`必须`有一个空行。 示例: ``` bar($arg1); Foo::bar($arg2, $arg3); ``` 参数列表`可以`被拆分成多个有一个缩进的后续行。如果这么做,列表中的第一项必须放在下一行,并且每一行`必须`只有一个参数。 ``` bar( $longArgument, $longerArgument, $muchLongerArgument ); ``` 5. 控制结构 --------------------- 对于控制结构的样式规则概括如下: - 控制结构关键词之后`必须`有一个空格 - 左括号之后`不可`有空格 - 右括号之前`不可`有空格 - 在右括号和左花括号之间`必须`有一个空格 - 代码主体`必须`有一次缩进 - 右花括号`必须`主体的下一行 每个结构的主体`必须`被括在花括号里。这结构看上去更标准化,并且当加新行的时候可以减少引入错误的可能性。 ### 5.1. `if`,`elseif`,`else` 一个`if`结构看起来应该像下面这样。注意括号,空格,花括号的位置;并且`else`和`elseif`和前一个主体的右花括号在同一行。 ``` $value) { // foreach body } ``` ### 5.6. `try`, `catch` 一个`try catch`语句看起来应该像下面这样。注意括号,空格和花括号的位置。 ``` bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 ); ``` 7. 结论 -------------- 在该指南中有很多风格的元素和做法有意被忽略掉。这些包括但不局限于: - 全局变量和全局常量的声明 - 方法声明 - 操作符和赋值 - 行间对齐 - 注释和文档块 - 类名给你前缀和后缀 - 最佳实践 以后的建议`可以`修改和扩展该指南以满足这些或其他风格的元素和实践。 --- PSR-3 日志接口 ================ 本文档用来描述日志类库的通用接口。 主要目标是让类库获得一个`Psr\Log\LoggerInterface`对象并且使用一个简单通用的方式来写日志。有自定义需求的框架和CMS`可以`根据情况扩展这个接口,但`应当`保持和该文档的兼容性,这将确保使用第三方库和应用能统一的写应用日志。 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119][]. 关键词`实现者`在这个文档被解释为:在日志相关的库和框架实现`LoggerInterface`接口的人。用这些实现的人都被称作`用户`。 [RFC 2119]: http://tools.ietf.org/html/rfc2119 1. 规范 ----------------- ### 1.1 基础 - `LoggerInterface`暴露八个接口用来记录八个等级(debug, info, notice, warning, error, critical, alert, emergency)的日志。 - 第九个方法是`log`,接受日志等级作为第一个参数。用一个日志等级常量来调用这个方法的结果`必须`和调用具体等级方法的一致。如果具体的实现不知道传入的不按规范的等级来调用这个方法`必须`抛出一个`Psr\Log\InvalidArgumentException`。用户`不应`自定义一个当前不支持的未知等级。 [RFC 5424]: http://tools.ietf.org/html/rfc5424 ### 1.2 消息 - 每个方法都接受字符串,或者有`__toString`方法的对象作为消息。实现者可以对传入的对象有特殊的处理。如果不是,实现者`必须`将它转换成字符串。 - 消息`可以`包含`可以`被上下文数组的数值替换的占位符。 占位符名字`必须`和上下文数组键名对应。 占位符名字`必须`使用使用一对花括号为分隔。在占位符和分隔符之间`不能`有任何空格。 占位符名字`应该`由`A-Z`,`a-z`,`0-9`,下划线`_`和句号`.`。其它的字符作为以后占位符规范的保留。 实现者可以使用占位符来实现不同的转义和翻译日志成文。用户在不知道上下文数据是什么的时候`不应`提前转义占位符。 下面提供一个占位符替换的例子,仅作为参考: ``` /** * Interpolates context values into the message placeholders. */ function interpolate($message, array $context = array()) { // build a replacement array with braces around the context keys $replace = array(); foreach ($context as $key => $val) { $replace['{' . $key . '}'] = $val; } // interpolate replacement values into the message and return return strtr($message, $replace); } // a message with brace-delimited placeholder names $message = "User {username} created"; // a context array of placeholder names => replacement values $context = array('username' => 'bolivar'); // echoes "Username bolivar created" echo interpolate($message, $context); ``` ### 1.3 上下文 - 每个方法接受一个数组作为上下文数据,用来存储不适合在字符串中填充的信息。数组可以包括任何东西。实现者`必须`确保他们对上下文数据足够的掌控。在上下文中一个给定值`不可`抛出一个异常,也`不可`产生任何PHP错误,警告或者提醒。 - 如果在上下文中传入了一个`异常`对象,它必须以`exception`作为键名。记录异常轨迹是通用的模式,如果日志底层支持这样也是可以被允许的。实现者在使用它之前`必须`验证`exception`的键值是不是一个`异常`对象,因为它`可以`允许是任何东西。 ### 1.4 助手类和接口 - `Psr\Log\AbstractLogger`类让你非常简单的实现和扩展`LoggerInterface`接口以实现通用的`log`方法。其他八个方法将会把消息和上下文转发给它。 - 类似的,使用`Psr\Log\LoggerTrait`只需要你实现通用的`log`方法。记住traits不能实现接口前,你依然需要`implement LoggerInterface`。 - `Psr\Log\NullLogger`是和接口一个提供的。它`可以`为使用接口的用户提供一个后备的“黑洞”。如果上下文数据非常重要,这不失为一个记录日志更好的办法。 - `Psr\Log\LoggerAwareInterface`只有一个`setLogger(LoggerInterface $logger)`方法可以用来随意设置一个日志记录器。 - `Psr\Log\LoggerAwareTrait`trait可以更简单的实现等价于接口。通过它可以访问到`$this->logger`。 - `Psr\Log\LogLevel`类拥有八个等级的常量。 2. 包 ---------- 作为[psr/log](https://packagist.org/packages/psr/log) 的一部分,提供接口和相关异常类的一些描述以及一些测试单元用来验证你的实现。 3. `Psr\Log\LoggerInterface` ---------------------------- ``` 标签: PHP, 代码规范