PHP编码规范

技术文档网 2021-04-15

本规则适用于使用PHP语言编写应用的人员。一经定义,PHP编写时统一遵循此规范

本规范包括PHP编写时命名、缩进、文件结构、注释等一系列定义。

目标 :公司PHP编码形成统一风格,编码人员能够互相理解对方编写之意图。

1. 代码规范

1.1 文件夹命名
  • 如果有框架定义,则文件夹命名统一按照框架制定的规则,如果框架不定义,则统一使用小写字母。

    以Lumen为例,项目下的第一级目录全部以小写字母命名。除app文件夹外,其它目录也是全部使用小写字母命名。 app目录下文件夹统一使用首字符大写命名。


1.2 文件及命名
  • 类文件,命名与类名称保持一致,必须统一使用大驼峰形式。

    // CacheManger.php
    
    class CacheManger {
      //...
    }
    
  • 配置文件,必须统一使用字母小写形式命名

    // config/jwt.php
    
    return [
      //...
    ]
    
  • 普通工具脚本,必须统一使用小驼峰命名

    // tools/uploadImage.php
    
    $i=1;
    dosth();
    
  • 只含有php代码的文件,结尾处忽略掉 "?>", 以防止多余的空格或者其它字符影响到代码。

  • 文件的编码必须为UTF-8字符集

  • 文件换行必须以Unix换行\n为准,不允许出现\r\n换行。 注:通过git可配置

  • 如果是接口类,则文件以I开头,如 IAuthedUser。 如果是抽象类,则以Abs开头,如AbsAppClient

  • 接口类和抽象类的实现,必须在文件命名中强调其继承哪个接口或抽象.

    // 命名的准确
    
    interface IAuthedUser {}
    abstract AbsAppClient {}
    
    class WeixinAuthedUser implements IAutheduser { }
    class MessageAppClient extends AbsAppClient {}
    

1.3 变量命名
  • 全局变量命名使用大驼峰,前缀加上_,所有单词首字母大写。

  • 常量统一使用大写,中间分隔使用_

  • 私有变量命名小驼峰,前缀加上_

  • 变量命名确认以英文名词为主。

  • 变量如果是类的对象,必须使用注释,使用@var定义对象所属的类

  • 必须注意单复数,变量如果是数组列表,则以s/es/List为结尾

  • 变量定义示例

    // 全局变量
    $_System_Config = config('myconfig');
    $_Root_Path     = '/';
    
    // 常量
    define('CURRENT_SCRIPT','index_php');
    const TRANSCATION_TYPE = 'income';
    
    // 私有变量(protected不在此列)
    private $_orderCnt = 0;
    protected $_salaryAmount = 0;
    
    /**
     * 我的订单列表
     * @var array
     */
    private $myOrderList = [];
    
    /**
     * 客户连接对象
     * @var ClientConnection|null
     */
    private $peerConnection = null;
    

1.4 类、方法、对象命名
  • 类统一使用大驼峰形式命名,与文件名必须保持一致。
  • 自编写的类一般遵循名词或名词短语来进行命名。
  • 框架中的一些类的命名参考 ()
  • 类的动作方法 ,一般使用【动词+名词】方式进行命名,例如 sendMessage / getAttr / setAttr / postLogin等
  • 类的属性和变量字段,使用小写字母或者小写驼峰方式命名
  • 类的private字段和方法,必须使用带_前缀的方式命名
  • 常量值,统一使用大写。
  • PHP自定义类示例参考

1.5 缩进和注释
  • 缩进采用4空格进行缩进,禁止使用TAB制表符。

  • 所有的类、函数、方法定义都需要进行注释。

  • 一般php注释遵循phpdocumentor规范, phpdocumentor

  • 如果是API的接口,则提供PHP APIDOC的相关注释 APIDOC

  • 注释

    // ------- 文件的注释 -------
    /**
     * Created by Qingger.
     * User: shipfi
     * Date: 2016/9/22
     * Time: 15:49
     */
    
    // ------- 类的注释 -------
    /**
     * 所有应用Controller的基类,提供了一般性请求/应答的共通实现
     * @desc 如有必要,通过desc描述详细的类的功能
     * Class BasicController
     * @package App\Http\Controllers
     */
    class BasicController extends Controller
    {
       // ------- 变量的注释,如果变量为 Array/Object类型,一定要使用@var说明其类型定义 -------
    
       /**
         * 缓存管理对象
         * @var AppCacheManager|null
         */
        protected $appCacheManager = null;
    
        const MY_RET = GlobalErrCode::ERR_SUCCESS;
    
          /**
         * @param Request $request
         * @param AppCacheManager $appCacheManager
         */
        public function __construct(Request $request,AppCacheManager $appCacheManager){
            $this->requestHandler  = $request;
            $this->appCacheManager = $appCacheManager;
            DB::connection()->enableQueryLog();
        }
    
       // ------- 方法的注释,参数如果为Array/Object类型,则一定需要指明 -------
    
        /**
         * 记录Debug日志信息
         * @desc : 参考----
         * @param $message
         * @param array $moreInfo
         */
        protected function debugLogIt($message,array $moreInfo=[]) {
            Log::debug($message,$moreInfo);
        }
    
    }
    

1.6 代码和语句
  • 两元运算符,前后使用空格

    $ret = $age>18 ? 'adult' : 'children';
    
  • 变量赋值必须保持相等间距和排列

    $newQyAgents = array_values(array_rename_keys($qyAgents,[
                    'agent_id'              => 'agentId',
                    'agent_name'            => 'agentName',
                    'agent_round_logo_url'  => 'agentRoundLogo',
                    'agent_square_logo_url' => 'agentSquareLogo',
                    'agent_app_id'          => 'appId'
    ]));
    
    if($corpMangerIns) {
                    $ret['corpUserManger']['corpUserId']     = $corpMangerIns->getMyUserId();
                    $ret['corpUserManger']['corpUserEmail']  = $corpMangerIns->getMyUserEmail();
                    $ret['corpUserManger']['corpUserMobile'] = $corpMangerIns->getMyUserMobile();
    }
    
  • 每行代码长度应控制在80个字符以内,最长不超过120个字符, 如超过则另起一行

    $qyAuthAppGrpIns = (new QyAuthAppGrp())->getInstanceBySuiteNameCorpId(
                    $suiteName,
                    $this->requestHandler->input('corpId')
                );
    
  • 每行结尾不允许有多余空格

  • 在类中(尤其是在Model),对于每个属性的访问, 统一使用get/set方法

    class MPAuthAppGrp extends BaseModel
    {
          public function getMyCallBackUrl()  { return isset($this->grp_callback_url) ? $this->grp_callback_url : null; }
        public function getMyGroupAppId()   { return isset($this->grp_app_id) ? $this->grp_app_id : null; }
        public function getMyWXAppId()      { return isset($this->auth_wx_app_id) ? $this->auth_wx_app_id : null; }
        public function getMyWXAppName()    { return isset($this->auth_wx_app_name) ? $this->auth_wx_app_name : null; }
        public function getMyGrpCode()      { return isset($this->grp_code) ? $this->grp_code : null; }
        public function getMyOpenAppId()    { return isset($this->opentp_appid) ? $this->opentp_appid : null; }
        public function getMyOpenAppName()  { return isset($this->opentp_name) ? $this->opentp_name : null; }
    }
    
  • 语句流程

    /** if / else 语句规范 **/
    if($age>1 && $age<10) {
      echo '1';
    } else if($age>30 && $age<=60) {
      echo '2';
    } else {
      echo '3';
    }
    
    /* switch语句规范 */
    switch($status) {
      // 严禁使用魔数,如 case 10:
      case OrderStatus::NO_PAY_STATUS:
         echo '1';
         break;
      case OrderStatus::HAS_PAY_STATUS:
         echo '2';
         break;
      default:
         break;
    }
    
    /* while语句 */
    while($condition) {
      // do sth
    }
    
    /* foreach语句 */
    foreach($a)
    
  • 使用 array 类型符声明关联数组的时候,我们鼓励把它分成多个行,只是我们必须同时保证每行的键与值的对齐,以保持美观。

  • 类中的所有代码都必须用四个空格来进行缩进。

  • 每个 php 文件只允许声明一个类。

  • 任何类变量的声明都必须放在类顶部,先于任何函数的声明。

  • 类中的方法必须总是用 private,protected 或者 public 来声明其作用域。

  • 对于方法的变量参数,如果参数确定为对象或数据,则必须在参数中给出变量提示:

    public function foo(AbsContract $obj, array options) {
      // do sth
    }
    
  • 代码做到复用,对于相同听代码逻辑,严禁出现在两个函数或者两个文件内,如果逻辑相同,使用重构提取共用性。

  • 一个函数的逻辑实现严禁超过一屏(非常特殊或者逻辑简单可理解的除外)。如果业务复杂,使用多个函数实现。

  • 一个函数中不能出现以下复杂的if/else逻辑判断, 简单规则,每个函数只允许一个if/elseif/else嵌套层。

    if($condition1) {
       if($condition2) {
          // do sth
       } else if ($condition3) {
          // do sth
       } else {
           if($condiont4) { // do sth.. }
          // do sth
       }
    } else {
      // do sth
    }
    

1.7 变量的定义和使用
  • 代码中,类的变量必须做到先定义后使用.

  • 变量使用时,尤其是数组变量,一定要判断其是否被设置

    $sItem = isset($items['key']) ? $item['key'] : null;
    
  • 在定义和使用变量时一定要明确其类型

    // 模型变量定义
    $objectModel = new ObjectModel();
    $objectInstance = $objectModel->find(1);
    
    // 基本类型:boolean
    $isAuthed = $objectInstance->getMyAuthedFlag();
    
    // 基本类型:int
    $cntAccount = 1;
    
    // date类型
    $dtToday   = Carbon::now();
    $tsExpires = time() + 3800;
    
    // 基本类型:array
    $accountList = [1,2,3];
    $acounts     = [1,2,3];
    
    // 基本类型: Map
    $personInfo = ['name'=>'a','sex'=>'m','age'=>10];
    
    // 基本类型对象: object
    $clientInstance = $this->getClient();
    
    // foreach使用时尤其是需要明确变量的单复数
    foreach($items as $key=>$item) {
      // do sth
    }
    

1.8 其它
  • 对API接口和复杂的返回数据,必须进行注释。以能够在代码中准确的了解接口所实现的功能、接口所接收的数据、接口所返回的数据。
  • 修改代码时,一定要保持注释同步,在IDE中严禁出现带黄线提示的注释
  • 未完成的功能使用TODO标记,如果函数接口层已经定义好,则在函数体内抛出暂时无法实现的异常

相关文章

  1. 如何通过xhprof分析性能

    使用方法 xhprof_enable(); /** ... 要检查的php代码 ... **/ $xhprof_data = xhprof_disable(); // 引入xhprof_lib i

  2. LUMEN API Controller 规范

    1. 第三方依赖库规范 在使用LUMEN实现API接口时,以下库必须需要包含在composer包依赖中,以实现代码编写的一些规范 dingo/api : 实现API接口库 vlucas/phpdo

  3. PHP文件锁

    共享锁(LOCK_SH) 什么时候加共享锁? 当在读取数据的时候同时进行着其他的写操作,这个时候需要对文件加共享锁,否则无论有没有对写操作加写锁都会写入成功,导致数据不一致 当文件获得共享锁时,其他

  4. Hello-Risen-程序

    首先需要说明的是,您下载到的文件包含两部分,其中src中是开发源码,用于对Risen框架本身的开发,risen 目录中是通过源码生成的包含debug和release版本的框架程序,用于您应用程序的开发

  5. PHP自定义类示例(Weixin消息解析类)

    PHP自定义类示例(Weixin消息解析类) /** * Created by Qingger. * User: jsspf * Date: 2017/3/24 * Time: 10:50

随机推荐

  1. 如何通过xhprof分析性能

    使用方法 xhprof_enable(); /** ... 要检查的php代码 ... **/ $xhprof_data = xhprof_disable(); // 引入xhprof_lib i

  2. LUMEN API Controller 规范

    1. 第三方依赖库规范 在使用LUMEN实现API接口时,以下库必须需要包含在composer包依赖中,以实现代码编写的一些规范 dingo/api : 实现API接口库 vlucas/phpdo

  3. PHP文件锁

    共享锁(LOCK_SH) 什么时候加共享锁? 当在读取数据的时候同时进行着其他的写操作,这个时候需要对文件加共享锁,否则无论有没有对写操作加写锁都会写入成功,导致数据不一致 当文件获得共享锁时,其他

  4. Hello-Risen-程序

    首先需要说明的是,您下载到的文件包含两部分,其中src中是开发源码,用于对Risen框架本身的开发,risen 目录中是通过源码生成的包含debug和release版本的框架程序,用于您应用程序的开发

  5. PHP自定义类示例(Weixin消息解析类)

    PHP自定义类示例(Weixin消息解析类) /** * Created by Qingger. * User: jsspf * Date: 2017/3/24 * Time: 10:50