PHP - Yii2编码规范/风格[PSR-1/PSR-2]

编码规范还是要了解的,但是有时候太多记不住/记不全,所以更好的解决方案是通过插件/脚本

1. 自动化工具

StyleCI // https://styleci.io/
如果你的代码格式不是很完美,不必担心,StyleCI会在提交代码时自动为我们修正代码风格以保持和 Laravel 仓库代码一致,从而让我们更加专注于代码内容而非风格。

2. vscode插件

PHP Intelephense - Visual Studio Marketplace // PHP Intelephense

  

文档阅读

PSR-11- 学习/实践_穿素白衫的中少年的博客-CSDN博客

PSR-1-basic-coding-standard

PSR-2-coding-style-guide

1.综述

总的来说,我们使用的是与PSR-2兼容的样式,所以应用于PSR-2的所有内容也应用于我们的代码样式。

备注: [红色的文字表示个人要注意的地方]

文件必须使用<?php或< ?=标记。  
文件末尾应该有一个换行符。//这个真的没有意识到
对于PHP代码,文件只能使用UTF-8,不能使用BOM。//通过IDE新建文件,会帮我们做,但是: 通过文本编辑器创建时要注意
代码必须使用4个空格缩进,而不是制表符。
类名必须用StudlyCaps声明。
类常量必须在所有带有下划线分隔符的大写字母中声明。
方法名必须在camelCase中声明。
必须在camelCase中声明属性名。
如果属性名是私有的,则它们必须以初始下划线开头。//有时候会忘记
总是使用elseif而不是elseif。//有时候会忘记

上面是PSR-1

https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md

2.文件

2.1 PHP标签
PHP代码必须使用<?php ?>或者<?=标记; 它一定不能使用其他标记变体,比如<?
如果文件只包含PHP,那么它后面不应该有?>   // 确实如此,一直都不写
不要在行尾添加尾随空格  // 有时候会有,但很应该很少
任何包含PHP代码的文件都应该以扩展名. PHP结束


2.2 字符编码
PHP代码只能使用UTF-8,不能使用BOM

3.类名

类名必须用StudlyCaps【即大驼峰原则】声明  例如,控制器,模型

4.类

术语“类”指这里的所有类和接口。
类应该使用CamelCase【大驼峰】命名。
大括号应该总是写在类名下面的行上。// 总是觉得这样不好看
每个类都必须有一个符合PHPDoc的文档块。//有时候写,有时候不写,视情况而定
类中的所有代码都必须缩进4个空格。
一个PHP文件中应该只有一个类。// 按理说是如此,但是有时候会有多个类,还有多个全局函数,或者直接PHP代码【常常用于PHP原生项目】,适情况而定
所有类都应该有namespace。//并不是如此,如果之前的原生项目,可能就没有用到命名空间
类名应该与文件名匹配。类命名空间应该匹配目录结构。// 总是努力保持如此,但不是必须如此

/**
 * Documentation
 */
class MyClass extends \yii\base\BaseObject implements MyInterface
{
    // code
}

4.1 常量

类常量必须在所有带有下划线分隔符的大写字母中声明。例如:

<?php
class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}

4.2 属性

当声明public类成员时,显式地指定public关键字 
公共变量和受保护变量应该在任何方法声明之前在类的顶部声明。

私有变量也应该在类的顶部声明,但是如果它们只与类方法的一小部分相关,则可以在处理它们的方法之前添加。// 这个还真是不太清楚,请谨记
类中属性声明的顺序应该根据其可见性升序: 从public 到 protected 再到 private【public > protected > private】// 好的
对于具有相同可见性的属性,没有严格的排序规则。// 还是建议按照下方代码中使用的先后顺序书写
为了更好的可读性,属性声明之间不应该有空行,属性和方法声明部分之间不应该有两行空行

应该在不同的可见性组之间添加一行空白。// 有时候便是如此做,但是不总是如此。


私有变量应该像$_varName那样命名。// 总是以为是个别人只管如此,然后okay,  受保护的属性不可以_开头? TBD
公共类成员和独立变量的命名应该使用第一个字母小写的$camelCase。
使用描述性名称。像$i和$j这样的变量最好不要使用。// 个人认为不需必须如此,因为有时,也不需要一定去描述


例如

<?php
class Foo
{
    public $publicProp1;//相同可见性的属性之间,没有空行
    public $publicProp2;

    protected $protectedProp;//不相同可见性的属性之间,则有一行空行,下同

    private $_privateProp;


    public function someMethod()//属性和方法之间,可应该有两行空行
    {
        // ...
    }
}

4.3 方法

函数和方法的命名应该使用首字母小写的camelCase
名称本身应该是描述性的,指示函数的用途 // 理应如此
类方法应该始终使用私有、受保护和公共修饰符声明可见性,不允许var  // 了解
函数的左大括号应该位于函数声明之后的行上  // 这个跟类名是一致的,之前一直认为是不一致的,但是还是觉得不美观

/**
 * Documentation
 */
class Foo
{ //看到花括号是在类名下面
    /**
     * Documentation
     */
    public function bar()
    { //看到花括号是在类的方法名下面,同类名相同
        // code
        return $value;
    }
}

4.4 PHPDoc块 【注释块】

@param、@var、@property和@return必须声明类型为bool、int、string、array或null。您还可以使用类名,如Model或ActiveRecord。
对于类型化数组,使用ClassName[] // 不甚明白
PHPDoc的第一行必须描述方法的用途。// 一直是这么做的
如果方法检查了某些东西(isActive、hasClass等),第一行应该以检查是否  // 好的
@return应该显式地描述将返回的确切内容  // 没这么做过,记下

/**
 * Checks whether the IP is in subnet range
 *
 * @param string $ip an IPv4 or IPv6 address
 * @param int $cidr the CIDR lendth
 * @param string $range subnet in CIDR format e.g. `10.0.0.0/8` or `2001:af::/64`
 * @return bool whether the IP is in subnet range
 */
 private function inRange($ip, $cidr, $range)
 {
   // ...
 }

4.5 构造函数

应该使用_construct而不是PHP 4风格的构造函数 

5.PHP

5.1 类型

所有PHP类型和值都应该使用小写。这包括true、false、null和array。//好吧,有时候NULL会用大写,改正
更改现有变量的类型被认为是一种不好的实践。除非确实需要,否则不要编写这样的代码。//虽然php是弱类型,语法上并没有问题,但是确实会反应我的编码习惯甚至技术水平

public function save(Transaction $transaction, $argument2 = 100)
{
    $transaction = new Connection; // bad  跟上面的参数类型不一致
    $argument2 = 200; // good
}

5.2 字符串

如果字符串不包含变量或单引号,则使用单引号  // 这个是从性能上考虑的,单引号执行速度更快

$str = 'Like this.';

[单双引号的各有适用场景,具体见两者的区别]

如果字符串包含单引号,可以使用双引号来避免额外的转义。

变量替换 [Variable substitution]

$str1 = "Hello $username!";
$str2 = "Hello {$username}!";

以下内容是不允许的:

$str3 = "Hello ${username}!"; // 不允许,但还是会正常解析执行

连接
连接字符串时,在圆点【.】周围添加空格:

$name = 'Yii' . ' Framework';  // 一向如此,美观

当字符串很长时,格式如下: // 了解了

$sql = "SELECT *"
    . "FROM `post` "
    . "WHERE `id` = 121 ";

5.3 数组

对于数组,我们使用PHP 5.4短数组【即[ ]】语法。
数值索引
不要使用负数作为数组索引。// 还是没试过,似乎会转化为自然数? 答案:并不会

$test = [-1=>1,-2=>2];
var_dump($test);

输出:
array(2) {
  [-1]=>
  int(1)
  [-2]=>
  int(2)
}

在声明数组时使用以下格式:

$arr = [3, 14, 15, 'Yii', 'Framework']; // 总是如此,简洁美观

如果一行有太多的元素: // 更多的是用于书写配置时

$arr = [
    3, 14, 15,
    92, 6, $test,
    'Yii', 'Framework',
];

关联
关联数组使用以下格式:

$config = [
    'name' => 'Yii',
    'options' => ['usePHP' => true],
];

5.4 控制语句

控件语句条件必须在圆括号前后各有一个空格  // 有时候会如此
括号内的运算符应该用空格分隔  // 大部分时候如此
左大括号在同一条直线上
右大括号在新行上
始终对单行语句使用大括号  // 好吧,之前总是如此,但是现在总是不如此,具体怎么做,你决定

if ($event === null) {
    return new Event();
}
if ($event instanceof CoolEvent) {
    return $event->instance();
}
return null;


// the following is NOT allowed: // 说的是不应该如此
if (!$model && null === $event)
    throw new Exception('test');

更应该避免在return之后使用 else。使用 guard conditions // [涉及的写法,确实困惑过,还是有点困惑]

$result = $this->getResult();
if (empty($result)) {
    return true;
} else {
    // process result
}

// 要比下面的好

$result = $this->getResult();
if (empty($result)) {
   return true;
}

// process result

Replace Nested Conditional with Guard Clauses【用保护子句替换嵌套条件句】

// 嵌套条件句
function getPayAmount() {
  let result;
  if (isDead)
    result = deadAmount();
  else {
    if (isSeparated)
      result = separatedAmount();
    else {
      if (isRetired)
        result = retiredAmount();
      else
        result = normalPayAmount();
    }
  }
  return result;
}

// 保护子句  推荐使用
function getPayAmount() {
  if (isDead) return deadAmount();
  if (isSeparated) return separatedAmount();
  if (isRetired) return retiredAmount();
  return normalPayAmount();
}

开关[switch子句]
使用以下格式切换:

switch ($this->phpType) { // 注意要将数据的类型转换回来
    case 'string':
        $a = (string) $value;
        break;
    case 'integer':
    case 'int':
        $a = (int) $value;
        break;
    case 'boolean':
        $a = (bool) $value;
        break;
    default:
        $a = null;
}

5.5 函数调用

doIt(2, 3);// 参数之间,有空格

doIt(['a' => 'b']);

doIt('a', [
    'a' => 'b',
    'c' => 'd',
]);

5.6 匿名函数(lambda)声明

注意 function/use 令牌和开括号之间的空格:

// good
$n = 100;
$sum = array_reduce($numbers, function ($r, $x) use ($n) {  //可以看到function 和 use 左右都是有空格的
    $this->doMagic();
    $r += $x * $n;
    return $r;
});

// bad
$n = 100;
$mul = array_reduce($numbers, function($r, $x) use($n) {
    $this->doMagic();
    $r *= $x * $n;
    return $r;
});

文档 [再说][均可以借助IDE模仿来写,而且有时候也不是必须要写的]

有关文档语法,请参考phpDoc。
没有文档的代码是不允许的。
所有类文件都必须在每个文件的顶部包含一个“文件级”docblock,并且在每个类的上面立即包含一个“类级”docblock。
如果方法不返回任何东西,就不需要使用@return。// 好吧,这时我总会返回true
扩展自yii\base\BaseObject的类中的所有虚拟属性都用类doc块中的@property标记记录下来。通过在build目录中运行./build php-doc,可以从相应的getter或setter中的@return或@param标记自动生成这些注释。您可以向getter或setter添加@property标记,以便在描述与@return中声明的不同时显式地为这些方法引入的属性提供文档消息。举个例子:

 <?php
  /**
   * Returns the errors for all attribute or a single attribute.
   * @param string $attribute attribute name. Use null to retrieve errors for all attributes.
   * @property array An array of errors for all attributes. Empty array is returned if no error.
   * The result is a two-dimensional array. See [[getErrors()]] for detailed description.
   * @return array errors for all attributes or the specified attribute. Empty array is returned if no error.
   * Note that when returning errors for all attributes, the result is a two-dimensional array, like the following:
   * ...
   */
  public function getErrors($attribute = null)

File

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

Class

/**
 * Component is the base class that provides the *property*, *event* and *behavior* features.
 *
 * @include @yii/docs/base-Component.md
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Component extends \yii\base\BaseObject

Function / method

/**
 * Returns the list of attached event handlers for an event.
 * You may manipulate the returned [[Vector]] object by adding or removing handlers.
 * For example,
 *
 * ```
 * $component->getEventHandlers($eventName)->insertAt(0, $eventHandler);
 * ```
 *
 * @param string $name the event name
 * @return Vector list of attached event handlers for the event
 * @throws Exception if the event is not defined
 */
public function getEventHandlers($name)
{
    if (!isset($this->_e[$name])) {
        $this->_e[$name] = new Vector;
    }
    $this->ensureBehaviors();
    return $this->_e[$name];
}

Markdown 【省略】

Comments【注释】

一行注释,应该以 // 而不是#开头。
一行注释,应该在它自己的行上。// 理应如此

额外规则【Additional rules】

=== [] vs . empty()
尽可能使用empty()。

多个返回点 【multiple return points】

当嵌套条件开始变得混乱时,尽早返回。如果方法很短,也没有关系。

self vs. static

除下列情况外,请始终使用 static:
访问常量必须通过self: self::MY_CONSTANT来完成
访问私有静态属性必须通过self: self::$_events来完成
它允许在有意义的方法调用中使用self,例如对当前实现的递归调用,而不是扩展类实现。

用于“不要做某事”的值 【value for "don't do something"】

允许配置组件不做某些事情的属性应该接受false值。不应该假定为null、''或[]。

目录/命名空间名称【Directory/namespace names】

使用小写
用复数形式表示表示对象的名词(e.g. validators)
使用单数形式表示相关功能/特性的名称(例如web) 
更喜欢单字名称空间  // 优先选择
如果单个单词不合适,使用camelCase【小驼峰】// 待了解

6.参考

https://github.com/yiisoft/yii2/blob/master/docs/internals/core-code-style.md  // Yii 2 Core Framework Code Style

后续补充

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值