PHP
PHP编码规范与原则
本文档使用 MrDoc 发布
-
+
首页
PHP编码规范与原则
### 前言 > 💡 标准化带来的收益 1. 代码更加优雅,提高代码可读性。 2. 降低代码潜在BUG风险。 3. 增加拓展性和可维护性。 4. 对新成员更加友好。 ### PHP文件 1. 文件使用 Unicode (UTF-8) 编码(不带 BOM)保存。 > 💡 如果保存带BOM的编码,会在文件头输出类似ufeff的内容,会导致JSON等数据无法正常读取。 2. PHP文件不要写 "?>" 闭合标签结束,保持最后一行留空。 > 💡 防止在封闭标签之后有多余的空格、制表符等不可见字符,导致页面渲染出不可见字符可能导致页面错乱;在一个PHP文件中包含了另外一个PHP文件,并使用了header, setcookie, session_start等函数,而另外一个PHP文件中,因为封闭标签后面有多余的字符,那么会导致报错 3. 文件命名:类名.php,类名使用大驼峰式(StudlyCaps)写法。 4. 配置文件:全小写字母,多单词用"_"分隔.php; ### PHP编码规范 #### 代码注释 ##### 文件头部注释 > 💡 文件头部注释,建议使用IDE编译器自动生成,例如:在PhpStorm->设置->编辑器->文件和代码模板->Includes->PHP File Header ``` /** * Notes 描述 * Author ${USER} * Date ${DATE} ${TIME} */ ``` 生成如下头部注释 ```php /** * Notes 描述 * Author taoqiang * Date 2022/12/15 11:23 */ ``` ##### 方法注释 > 💡 方法注释,建议使用IDE编译器自动生成,例如:在PhpStorm->设置->编辑器->文件和代码模板->Includes->PHP Function Doc Comment ``` /** * @notes 描述 ${PARAM_DOC} * @return ${TYPE_HINT} ${THROWS_DOC} */ ``` 生成如下方法注释 ```php /** * @notes 描述 * @param string $tag * @return string */ public function example(string $tag) { return ""; } ``` ##### 单行注释 > 💡通常变量命名具有含义,例如:$sysConfigs = []; 下意识的理解为“系统配置”,但对于专业性较强或者自定义的变量命名,我们需要使用注释标注其含义。 ```php <?php // 投资资本回报率 $ROIC = 0; // 用于保存第三方xxx返回数据 $as = []; ``` #### 代码缩进 > 使用Tab键来缩进,每个Tab键长度设置为4个空格。 #### 关键字小写 > PHP 的关键字,必须小写,boolean 值:true,false,null 也必须小写。 #### 规范命名 1. 类命名规则:使用大驼峰式(StudlyCaps)写法,如 class Ocr; 2. 方法命名规则:使用小驼峰(cameCase)写法,如 public function basicGeneral(); 3. 函数命名规则:使用小写字母 + 下划线 写法,如 function send_msg(); 4. 变量命名规则:使用小驼峰(cameCase)写法,如 $varName; 5. 常量命名规则:所有字母都必须大写,词间以下划线分隔,如 const API_VERSION = '1.0.1'; 6. 命名长度规则:不超过 40 个字符,建议不超过 25 个字符,实在太长可以使用简写(缩写)并标注注释 7. 杜绝中英混杂命名,减少以拼音方式命名;使用言简意赅的命名,例如使用$data而不可使用$data1、$data2这样容易产生混淆的形式,如果使用$threadData、$postData这样更加一目了然。 #### 控制结构 ##### 基础规范 1. 控制关键字后必须有一个空格 2. 大括号"($var)"内$var前后不能有空格 3. ) 和 { 之间必须有一个空格 4. } 必须在代码块下面一行 5. 条件语句里不包含赋值语句 ```php <?php $var = rand(1, 10); if ($var > 5) { echo "当前随机数大于5"; } else { echo "当前随机数小于等于5"; } ``` ##### if, elseif, else 1. 将 elseif 代替 else if,更像一个控制关键字 2. 对于 if...return 等只包含简单判断的流控制语句,代码可不换行、不加花括号提高可读性 ```php <?php // 将 elseif 代替 else if,更像一个控制关键字 if ($expr) { // if body } elseif ($expr2) { // elseif body } else { // else body } // 对于 if...return 等只包含简单判断的流控制语句,代码可不换行、不加花括号提高可读性 if ($bool) return $something; ``` ##### swith, case ```php <?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 <?php while ($expr) { // structure body } do { // structure body; } while ($expr); ``` ##### for ```php <?php for ($i = 0; $i < 10; $i++) { // for body } ``` ##### foreach ```php <?php foreach ($iterable as $key => $value) { // foreach body } ``` ##### try, catch ```php <?php try { // try body } catch (FirstExceptionType $e) { // catch body } catch (OtherExceptionType $e) { // catch body } catch (ExceptionType $e) { // catch body } ``` ##### 闭包 1. 闭包的声明中在 function 关键词后必须有一个空格,在 use 关键词前后都必须有一个空格 2. { 必须与声明在一行,} 必须在代码块的下一行 ```php <?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body }; ``` ```php <?php $longArgsNoVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) { // body }; $noArgsLongVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgsLongVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgsShortVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ($var1) { // body }; $shortArgsLongVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; ``` #### 命名空间 ##### 完整的类名结构定义 ``` \<命名空间>(\<子命名空间>)*\<类名> ``` 1. 完整的类名必须要有一个顶级命名空间,被称为 "vendor namespace" 2. 完整的类名可以有一个或多个子命名空间 3. 完整的类名必须有一个最终的类名 4. 完整的类名中任意一部分中的下滑线都是没有特殊含义的 5. 完整的类名可以由任意大小写字母组成 6. 所有类名都必须是大小写敏感的 ##### 根据完整的类名载入相应的文件 1. 完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为“命名空间前缀”,其必须与至少一个“文件基目录”相对应; 2. 紧接命名空间前缀后的子命名空间必须与相应的”文件基目录“相匹配,其中的命名空间分隔符将作为目录分隔符。 3. 末尾的类名必须与对应的以 .php 为后缀的文件同名。 4. 自动加载器(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 | ##### 命名空间使用 1. 命名空间(namespace)的声明后面必须有一行空行 2. 当使用 use 关键字导入多个类时,则换行逐个 use 引入 3. 当使用 use 关键字导入类后使用 as 时,使用大驼峰式(StudlyCaps)别名 4. use 代码块之后必须有一行空行 ```php <?php /** * Notes 描述 * Author taoqiang * Date 2022/12/15 17:40 */ namespace Vendor\Package;// 命名空间(namespace)的声明后面必须有一行空行 use FooClass;// 当使用 use 关键字导入多个类时,则换行逐个 use 引入 use OtherClass; use BarClass as Bar; // 当使用 use 关键字导入类后使用 as 时,使用大驼峰式(StudlyCaps)别名 use OtherVendor\OtherPackage\BazClass; // use 代码块之后必须有一行空行 class Person { } ``` #### 类、属性、方法 > 💡指代所有的类、接口以及可复用代码块(traits) ##### 类定义 1. 首行为 <?php,后面不跟空格 2. 第二至六行为IDE自动生成的注释,其中 Notes 需要自行描述,后面空一行 3. extends 和 implements 关键字必须与类名字在一行 4. { 放在类名声明下一行顶格,} 必须在代码块后面一行 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; use OtherVendor\OtherPackage\ParentClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods } ``` ##### 常量 1. 类常量必须使用全部大写,单词间使用 _ 分隔 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; class ClassName { const VERSION = '1.0.1'; const CONST_NAME = 'something'; } ``` <a name="bK4GU"></a> ##### 属性 1. 所有属性必须有可见性声明(public/protected/private) 2. 每一行定义一个属性 3. 属性名称不能使用前导 _ 来指示 protected 或 private 的可见性 4. 属性与属性上下之间使用空行隔开 5. 属性注释格式 @var [类型] [变量名] [<描述>],如果晦涩难懂、模棱两可的属性命名请标注其描述 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; class ClassName { /** * @var Transport $transport Transport参数 */ public $transport; /** * @var array $params 客户端参数 */ protected $params; } ``` ##### 方法 1. 可见性(public/protected/private)必须被声明在所有方法上 2. 方法名之后不能有空格。{ 在 ) 下一行顶格对齐,} 必须在代码块后面一行。( 后不能有空格,) 前不能有空格 3. 方法内代码块长度不超过两屏(80 行),最好不超过一屏(40 行);超过了要求拆分方法 4. 方法内代码块嵌套层级不超过 4 级,最好不超过 3 级;超过了要求重构逻辑或抽象方法 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; class ClassName { /** * @notes 描述 * @param string $arg1 参数1 * @param string $arg2 参数2 * @param array $arg3 参数3 * @return array */ public function fooBarBaz(string $arg1, string $arg2, array $arg3 = []): array { return []; } } ``` ##### 方法参数 1. 在参数列表中,每个逗号前不能有空格,逗号后必须有一个空格 2. 带默认值的参数必须在参数列表的最后 3. 参数列表可以被分成多行,每个子序列带一个缩进;当这么做时,列表的第一项必须在下一行,并且之后每行一个参数 4. 当参数列表被分成多行时,) 必须放置在 { 的一行,且中间有一个空格 5. 参数如果是特定类型的对象的,该参数前显示声明对象类型 6. 【建议】方法参数建议不超过 5 个参数,一般不超过 8 个参数;如超过了,要求重构函数或以数据、对象作为参数传递 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; use FooClass; class ClassName { /** * @notes 描述 * @param FooClass $arg1 参数1 * @param string $arg2 参数2 * @param array $arg3 参数3 * @return array */ public function fooBarBaz( FooClass $arg1, string $arg2, array $arg3 = [] ): array { return []; } } ``` ##### abstract, final 和 static 1. 当存在时,abstract 和 final 声明必须在可见性声明之前 2. 当存在时,static 声明必须在可见性声明之后 ```php <?php /** * Notes 描述 * Author jungelcat * Date 2022/12/15 17:52 */ namespace Vendor\Package; abstract class ClassName { /** * @var string $foo */ protected static $foo; /** * @notes 更新数据 * @return mixed */ abstract protected function update(); /** * @notes 回收 * @return void */ final public static function recovery() { // method body } } ```
admin
2022年12月16日 13:09
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码