PHP 开发规范

规范遵循PHP-FIG组织推荐的PHP开发标准(PSR

PSR-1 是组织推荐的PHP开发规范

PSR-2 是组织推荐的代码风格

PSR-4 是组织推荐的类的自动加载规范

PSR-5 是组织推荐的文档注释规范

规范有点多,不一定记得住,所以第一期整理的规则是一些大家已经形成或者正在形成的路上的开发规范

规范的好处不用说了,提升团队协作的舒适度以及代码健壮性、安全性是毋庸置疑的。

PHP编程规约

命名规约
– 命名需要有意义,专有名词等特殊情况允许使用拼音(danyue)

// bad $a = 30; # 年龄 

// good $age = 30; # 年龄

– 方法名采用首字母小写的驼峰方式,类名采用首字母大写的驼峰方式,方法名首词采用动词加驼峰

// bad 
function calculate_salary()
{
// method body
}

// good
function calculateSalary()
{
// method body
}

// bad
class bizcode
{
// class body
}

// good
class BizCode
{
// class body
}

– 变量名都用驼峰

// good
$errorCode = 500;
 
// bad
$error_code = 500;
 
// 类的成员变量
class Code
{
  // good
  private $conf;
  // good
  protected $business;
}
 
class Code
{
  // bad
  private $_conf;
  // bad
  protected $_business;
}

- `建议`Api返回值中的字段名,是驼峰的命名方式 这个根据应用场景处理

– 常量定义大写,单词间以下划线分隔

// bad
define('app_path', __DIR__ . '/../application/');

// good
define('APP_PATH', __DIR__ . '/../application/');

class BizCode
{
  // bad
  const abc360        = 10;
  // good
  const LANDI         = 20;
}

– PHP关键字都小写, 常量 true 、false 和 null 也都小写

// bad
FOREACH ($students AS $student) {

}
// good
foreach ($students as $student) {

}

// bad
IF ($age > 18) {
  // condition body
} ELSE {
  // condition body
}

// good
if ($age > 18) {
  // condition body
} else {
  // condition body
}

// bad
DEFINE('DEBUG', true);

// good
define('DEBUG', true);

– `?>` 结束符在文件末尾省略

// bad
<?php
  echo 'Wow, non-blocking!';
?>

// good
<?php
  echo 'Wow, non-blocking!';

– 创建数组时统一使用 [] 代替 array()

// bad
$students = array();

// good
$students = [];

– if/for/foreach/while/switch/do 等保留字与括号之间都必须加空格。

// bad
if($expr1){
  // if body
}elseif($expr2) {
  // elseif body
}else{
  // else body;
}
 
// good
if ($expr1) {
  // if body
} elseif ($expr2) {
  // elseif body
} else {
  // else body;
}

// bad
foreach($iterable as $key=>$value){
  // foreach body
}

// good
foreach ($iterable as $key => $value) {
  // foreach body
}

– 在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使空代码

// bad
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;
}

// good
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;
}

– 所有的类都必须添加创建者和创建日期

// bad
<?php

namespace lib\api;

/**
 * ApiController基类
 * Class ApiController
 * @package lib\api
 */
class ApiController
{

}
 
// good
<?php
/**
 * User: xxx
 * Date: 2019/01/20
 * Time: 下午1:13
 */

namespace lib\api;
/**
 * ApiController基类
 * Class ApiController
 * @package lib\api
 */
class ApiController
{

}

– namespace声明后得有个空行,use 代码块放一起且上下保留空白行

// bad
namespace Vendor\Package;
use FooInterface;
 
use BarClass as Bar;
 
use OtherVendor\OtherPackage\BazClass;
// class declaration

// good
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// class declaration

– extends implements 和类声明在一行

// bad
namespace Vendor\Package;
 
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
 
class Foo extends Bar
implements FooInterface
{

}

// good
namespace Vendor\Package;
 
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
 
class Foo extends Bar implements FooInterface
{

}
// 其他

– 类的起始大括号单独一行;类的结束大括号必须放在正文后面的下一行上

// bad
class Foo extends Bar implements FooInterface {
  // class body
}

// good
class Foo extends Bar implements FooInterface
{
  // class body
}

– 方法参数在定义和传入时,多个参数逗号后边必须加空格,  函数参数默认值放最后, 方法参数给能够强制指定类型的指定类型

// bad
function fooBarBaz($arg3 = [], &$arg2, $arg1)
{
  // method body
}

// good
function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
  // method body
}

– abstract, final 放在类的可见性描述符前面,static放在描述符后面

// bad
abstract class ClassName
{
  static protected $foo;

  protected abstract function zim();

  static public final function bar()
  {
  // method body
  }
}
 
// good
abstract class ClassName
{
  protected static $foo;
 
  abstract protected function zim();
 
  final public static function bar()
  {
  // method body
  }
}
- `建议`函数参数尽量不要超过4个, return 返回数据类型一致

– 方法、类、成员变量、复杂逻辑要注释清楚,注释遵循phpDocument

// bad
function foo($create_new)
{
  if ($create_new) {
  return new stdClass();
  }
  return null;
}

// good
/**
 * @param bool $create_new When true returns a new stdClass.
 *
 * @return stdClass|null
 */
function foo($create_new)
{
  if ($create_new) {
  return new stdClass();
  }
  return null;
}

– 注释的双斜线与注释内容之间有且仅有一个空格

// bad
//this is a doc

// good
// this is a doc

其他

– 开发服务时遵循SRP-职责单一,ISP-接口隔离原则,DRY -无重复代码原则, 接口业务单一。
– 框架内部提供了Session方法,一定要用框架的方法,勿直接使用$_SESSION设置
– 在高并发场景中,避免使用”等于”判断作为中断或退出的条件
– 非特殊情况,忌循环查询数据库(需要说明场景),涉及到数据库写操作,要有事务保证 
–  生产环境禁止输出 debug 日志
– 禁止向 HTML 页面输出未经安全过滤或未正确转义的用户数据
– 在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放的机 制,如数量限制、疲劳度控制、验证码校验,避免被滥刷而导致资损
– 对程序算法的复杂度要时刻考虑着,尤其是时间复杂度
– 所有sql语句必须被包装到model类中不允许出现在controller,service等地方
– 数据关联查询禁用出现与本模块或其它业务的关联查询 

工具统一

– PHPSTORM 

– 统一IDE模板