PSR-12 編碼規範擴充

文章轉發自專業的Laravel開發者社區,原始連接: https://learnku.com/laravel/t...

編碼風格擴充指南

文章中的關鍵詞 MUSTMUST NOTREQUIREDSHALLSHALL NOTSHOULD
SHOULD NOTRECOMMENDEDMAY ,和 OPTIONAL 都在 [RFC 2119][] 中進行來解釋。php

摘要

此規範起到繼承,擴展和替換 [PSR-2][] 的做用, 同時編碼風格遵照 [PSR-1][] 這個基礎編碼標準。
和 [PSR-2][] 同樣, 此規範的目的是減小不一樣人在閱讀代碼時認知衝突。 它經過列舉一套如何格式化 PHP 代碼的公共的規則和指望來實現這個目標。 PSR 力圖提供一套方法,編碼風格工具能夠利用,項目能夠遵照,開發人員能夠方便的在不一樣的項目中使用。當各個的開發人員在進行多項目合做的時候,它能夠幫助在這些項目中提供一套通用的指導。因此,本指南的價值不是規則自己,而是這些規則的共享。html

[PSR-2][] 在 2012 年被接受,隨後 PHP 經歷了不少變化,影響了編碼風格。同時 [PSR-2] 是 PHP 編碼時候的基礎功能,被普遍的採用。所以,PSR 力圖經過一種更加現代的方式說明 PSR-2 的內容和新功能,並對 PSR-2 進行更正。laravel

之前的語言版本

在整個文檔中,任何說明均可以被忽略,若是它們不存在於你項目所支持的 PHP 版本中。數組

例如

此示例包含如下一些規則做爲快速概述:閉包

<?php

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;

use function Vendor\Package\{functionA, functionB, functionC};

use const Vendor\Package\{ConstantA, ConstantB, ConstantC};

class Foo extends Bar implements FooInterface
{
    public function sampleFunction(int $a, int $b = null): array
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // 方法內容
    }
}

2. 總則

2.1 基本編碼標準

代碼必須遵循[PSR-1]中列出的全部規則。app

PSR-1中的術語 'StudlyCaps' 必須解釋爲 PascalCase (帕斯卡命名法:大駝峯式命名法),其中每一個單詞的第一個字母大寫,包括第一個字母。函數

2.2 文件

全部 PHP 文件只能使用Unix LF (換行符) 結尾。工具

全部的 PHP 文件都必須以非空行結尾,以一個 LF 結尾。編碼

在僅包含 PHP 代碼的文件中,必須省略結尾的 ?> 標記。spa

2.3 代碼行

行長度不得有硬限制。

行長度的軟限制必須爲120個字符。

行的長度不該超過80個字符;超過該長度的行應拆分爲多個後續行,每一個行的長度不該超過80個字符。

行尾不能有尾隨空格。

能夠添加空行以提升可讀性並指示相關的代碼塊,除非明確禁止。

每行不能有多個語句。

2.4 縮進

代碼必須爲每一個縮進級別使用4個空格的縮進,而且不能使用縮進標籤。

2.5 關鍵詞和類型

PHP 的全部關鍵字和類型 [[1]]關鍵字][類型] 都必須使用小寫。

PHP將來版本中新加的全部關鍵字和類型也都必須使用小寫。

類型關鍵字必須使用縮寫。使用 bool 而不是 boolean,使用 int 而不是 integer 等等。

3. 聲明、命名空間以及導入

一個PHP文件的頭部可能會包含多個塊。若是包含多個塊,則每一個塊都必須用空白行和其餘塊分隔,而且塊內不能包含空白行。全部的塊都必須按照下面的順序排列,若是不存在該塊則忽略。

  • PHP文件開始標籤: <?php
  • 文件級文檔塊。
  • 一個或多個聲明語句。
  • 命名空間聲明語句。
  • 一個或多個基於類的 use 聲明語句。
  • 一個或多個基於方法的 use 聲明語句。
  • 一個或多個基於常量的 use 聲明語句。
  • 其他代碼。

當文件包含HTML和PHP的混合代碼時,可使用上面列出的任何部分。若是是這種狀況的話,即時代碼的其餘部分包含有PHP結束符,而後再包含HTML和PHP代碼,聲明、命名空間和導入語句塊也必須放在文件的頂部。

何時開始 <?php 標籤位於文件的第一行,它必須位於本身的行,沒有其餘語句,除非它是一個包含 PHP 以外的標記的文件打開和關閉標記。

import語句不能之前導反斜槓開頭,由於它們必須始終徹底合格。

如下示例演示了全部塊的完整列表:

<?php

/**
 * This file contains an example of coding styles.
 */

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;
use Vendor\Package\AnotherNamespace\ClassE as E;

use function Vendor\Package\{functionA, functionB, functionC};
use function Another\Vendor\functionD;

use const Vendor\Package\{CONSTANT_A, CONSTANT_B, CONSTANT_C};
use const Another\Vendor\CONSTANT_D;

/**
 * FooBar is an example class.
 */
class FooBar
{
    // ... 其餘php代碼 ...
}

深度不能超過兩層的複合名稱空間,所以如下展現了容許的最大複合深度。

<?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\ClassA,
    SubnamespaceOne\ClassB,
    SubnamespaceTwo\ClassY,
    ClassZ,
};

而且不容許如下內容:

<?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\AnotherNamespace\ClassA,
    SubnamespaceOne\ClassB,
    ClassZ,
};

當但願在 PHP 外部包含標記的文件中聲明嚴格類型時打開和關閉標籤,聲明必須寫在文件的第一行而且包含在一個開始的 PHP 標籤,以及嚴格的類型聲明和結束標籤。

例如:

<?php declare(strict_types=1) ?>
<html>
<body>
    <?php
        // ... 其餘 PHP 代碼  ...
    ?>
</body>
</html>

聲明語句不能包含空格,而且必須徹底是 declare(strict_types=1) (帶有可選的分號終止符)。

容許使用塊聲明語句,而且必須按照如下的格式設置。注意的位置括號和間距:

declare(ticks=1) {
    // 一些代碼
}

4. 類,屬性,和方法

這裏的『類』指的是全部類,接口,以及 trait 。

任何註釋和語句 不得 跟在其右花括號後的同一行。

當實例化一個類時,後面的圓括號 必須 寫出來,即便沒有參數傳進其構造函數。

new Foo();

4.1 繼承和實現

關鍵字 繼承實現 必須 在類名的同一行聲明。

類的左花括號 必須 另起一行;右花括號 必須 跟在類主體的下一行。

類的左花括號 必須 獨自成行,且 不得 在其上一行或下一行存在空行。

右花括號 必須 獨自成行,且 不得 在其上一行存在空行。

<?php

namespace Vendor\Package;

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

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // 常量,屬性,方法
}

若是有接口, 實現 接口和 繼承父類 能夠 分爲多行,前者每行需縮進一次。當這麼作時,第一個接口 必須 寫在下一行,且每行 必須 只能寫一個接口。

<?php

namespace Vendor\Package;

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

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // 常量,屬性,方法
}

4.2 使用 trait

在類裏面用於實現 trait 的關鍵字 use 必須 在左花括號的下一行聲明。

<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;
}

每一個導入類的 trait 必須 每行一個包含聲明,且每一個包含聲明 必須 有其 use 導入語句。

<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;
use Vendor\Package\SecondTrait;
use Vendor\Package\ThirdTrait;

class ClassName
{
    use FirstTrait;
    use SecondTrait;
    use ThirdTrait;
}

在類文件中,若是在使用'use Trait'以後沒有其餘內容了 ,類名右大括號必須另起一行。

<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;
}

若有其餘內容,二者之間需空一行。

<?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;

    private $property;
}

當使用' insteadof '和' as '運算符時,它們必須如圖所示使用,注意縮進、間距和另起一行。

<?php

class Talker
{
    use A, B, C {
        B::smallTalk insteadof A;
        A::bigTalk insteadof C;
        C::mediumTalk as FooBar;
    }
}

4.3 屬性和常量

全部屬性 必須 聲明可見性。

若是你的項目 PHP 最小版本支持常量可見性( PHP 7.1 或以上),全部常量 必須 聲明可見性。

關鍵字 var 不得 用於聲明屬性。

每條聲明語句 不得 聲明多於一個屬性。

屬性名 不得 用單個下劃線開頭代表其受保護的或私有的可見性。也就是說,一個下劃線開頭顯然是沒有意義的。

類型聲明和屬性名之間 必須 有一個空格。

一個屬性聲明看上去以下所示:

<?php

namespace Vendor\Package;

class ClassName
{
    public $foo = null;
    public static int $bar = 0;
}

4.4 方法和函數

全部的方法 必須 事先聲明類型。

方法命名 必定不可 用單個下劃線來區分是 protectedprivate 類型。也就是說,不要用一個沒有意義的下劃線開頭。

方法和函數名稱中,方法命名後面 必定不可 使用空格。方法開始的花括號 必須 寫在方法聲明後自成一行, 結束花括號也 必須 寫在方法後面自成一行。開始左括號後和結束右括號前,都 必定不可 有空格符。

一個方法的聲明應該以下所示。注意括號,逗號,空格和花括號的位置:

<?php

namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // 方法主體
    }
}

一個函數的聲明應該以下所示。注意括號,逗號,空格和花括號的位置:

<?php

function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
    // 函數主體
}

4.5 方法和函數參數

在參數列表中, 不得 在每一個逗號前存在空格,且 必須 在每一個逗號後有一個空格。

方法和函數中帶有默認值的參數 必須 放在參數列表的最後。

<?php

namespace Vendor\Package;

class ClassName
{
    public function foo(int $arg1, &$arg2, $arg3 = [])
    {
        // 方法主體
    }
}

參數列表 能夠 分爲多行,每行參數縮進一次。當這麼作時,第一個參數 必須 放在下一行,且每行 必須 只能有一個參數。

當參數列表分紅多行時,右圓括號和左花括號 必須 放在同一行且單獨成行,二者之間存在一個空格。

<?php

namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // 方法主體
    }
}

當你定義一個返回值類型聲明時,冒號後面的類型聲明 必須 用空格符隔開。冒號和聲明 必須 在同一行,且跟參數列表後的結束括號之間沒有空格。

<?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(int $arg1, $arg2): string
    {
        return 'foo';
    }

    public function anotherFunction(
        string $foo,
        string $bar,
        int $baz
    ): string {
        return 'foo';
    }
}

在可空類型聲明中,問號和類型聲明之間不能有空格。

<?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(?string $arg1, ?int &$arg2): ?string
    {
        return 'foo';
    }
}

當在參數以前使用引用運算符 & 時,引用運算符以後不能有空格,例如上面的示例。

可變參數聲明的三個點和參數名稱之間不能有空格:

public function process(string $algorithm, ...$parts)
{
    // 函數體
}

當同時使用引用運算符和可變參數運算符時,它們之間不能有任何空格:

public function process(string $algorithm, &...$parts)
{
    // 函數體
}

4.6 abstract, final, and static

若是是 abstract and final ,那麼申明的時候必須是可見性聲明。

若是是 static ,聲明必須位於可見性聲明以後。

<?php

namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // 請求體
    }
}

4.7 方法和函數的調用

當咱們在進行方法或者函數調用的時候,方法或函數與左括號之間不能出現空格,在右括號以後也不能出現空格,而且在右括號以前也必定不能有空格。在參數列表中,每一個逗號前面必定不能有空格,每一個逗號後面也必定不能有空格。

<?php

bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

參數列表能夠分爲多行,每行後面縮進一次。這個作以後,列表中的第一行必須位於下一行,而且每一行必須只有一個參數。跨多個行拆分單個參數(就像匿名函數或者數組那樣)並不構成拆分參數列表自己。

<?php

$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);
<?php

somefunction($foo, $bar, [
  // ...
], $baz);

$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello ' . $app->escape($name);
});

5. 流程控制

以下是主要的流程控制風格規則:

  • 流程控制關鍵詞以後 必須 要有一個空格
  • 左括號後面 不能 有空格
  • 右括號前面 不能 有空格
  • 右括號與左大括號之間 必須 要有一個空格
  • 流程主體 必須 要縮進一次
  • 流程主體 必須 在左大括號以後另起一行
  • 右大括號 必須 在流程主體以後另起一行

每一個流程控制主體 必須 以封閉的括號結束。這將標準化流程結構,同時減小因爲流程中添加新的內容而引入錯誤的可能性。

5.1 if, elseif, else

if 結構以下。注意括號,空格,和大括號的位置;elseelseif 都在同一行,和右大括號同樣在主體的前面。

<?php

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

關鍵詞 elseif 應該 替換 else if,這樣控制關鍵詞看起來像一個詞。

括號中的表達式 可能 會被分開爲多行,每一行至少縮進一次。若是這樣作,第一個條件 必須 在新的一行。右括號和左大括號 必須 在同一行,並且中間有一個空格。條件中間的布爾控制符 必須 在每一行的開頭或者結尾,而不是混在一塊兒。

<?php

if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}

5.2 switch, case

switch 結構以下。注意括號,空格和大括號的位置。case 必須 縮進一次從switch開始, break 關鍵詞 (或者其餘終止關鍵詞) 必須 縮進和 care 主體保持一致。必須 要有一個像 // 不終止 這樣的註釋在不爲空且繼續的 care 主體之中。

<?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;
}

括號中的表達式 可能 會被分開多行,每一行至少要縮進一次。若是這樣作,第一個條件 必須 在新的一行。右括號和左大括號 必須 在同一行,並且中間有一個空格。條件中間的布爾控制符 必須 在沒一行的開頭或者結尾,而不是混在一塊兒。

<?php

switch (
    $expr1
    && $expr2
) {
    // structure body
}

5.3 while, do while

while 結構以下。注意括號,空格和大括號的位置。

<?php

while ($expr) {
    // structure body
}

括號中的表達式 可能 會被分開多行,沒一行至少要縮進一次。若是這樣作,第一個條件 必須 在新的一行。右括號和左大括號 必須 在同一行,並且中間有一個空格。條件中間的布爾控制符 必須 在沒一行的開頭或者結尾,而不是混在一塊兒。

<?php

while (
    $expr1
    && $expr2
) {
    // structure body
}

一樣的, do while 申明以下。注意括號,空格和大括號的位置。

<?php

do {
    // structure body;
} while ($expr);

括號中的表達式 可能 會被分開多行,沒一行至少要縮進一次。若是這樣作,第一個條件 必須 在新的一行。條件中間的布爾控制符 必須 在每一行的開頭或者結尾,而不是混在一塊兒。

<?php

do {
    // structure body;
} while (
    $expr1
    && $expr2
);

5.4 for

for 申明以下。注意括號,空格和大括號的位置。

<?php

for ($i = 0; $i < 10; $i++) {
    // for body
}

括號中的表達式 可能 會被分開多行,每一行至少要縮進一次。若是這樣作,第一個條件 必須 在新的一行。右括號和左大括號 必須 在同一行,並且中間有一個空格。

<?php

for (
    $i = 0;
    $i < 10;
    $i++
) {
    // for body
}

5.5 foreach

foreach 語句的寫法以下所示。請注意它的圓括號、空格和花括號。

<?php

foreach ($iterable as $key => $value) {
    // 迭代主體
}

5.6 trycatchfinally

一個 try-catch-finally 模塊包含下面這些內容。請注意它的圓括號、空格和花括號。

<?php

try {
    // try 主體
} catch (FirstThrowableType $e) {
    // 捕獲異常主體
} catch (OtherThrowableType | AnotherThrowableType $e) {
    // 捕獲異常主體
} finally {
    // finally 主體
}

6. 運算符

運算符的樣式規則按元數分組(其接受的操做數個數)。

當運算符周圍容許出現空格時, 能夠 出於可讀性目的打多個空格。

全部這裏沒描述的運算符暫不做限定。

6.1. 一元運算符

遞增 / 遞減運算符和操做數之間 不得 有任何空格。

$i++;
++$j;

類型轉換運算符的圓括號內部 不得 有任何空格:

$intValue = (int) $input;

6.2. 二元運算符

全部二進制 算術比較賦值按位邏輯字符串類型運算符必須在先後跟至少一個空格:

if ($a === $b) {
    $foo = $bar ?? $a ?? $b;
} elseif ($a > $b) {
    $foo = $a + $b * $c;
}

6.3. 三元運算符

條件運算符,也稱爲三元運算符,必須在 ?:這兩個字符之間:

$variable = $foo ? 'foo' : 'bar';

若是省略條件運算符的中間操做數,運算符必須遵循與其餘二進制比較運算符相同的樣式規則:

$variable = $foo ?: 'bar';

7. 閉包(Closures)

閉包聲明時必須在 function 關鍵字後留有1個空格,而且在 use 關鍵字先後各留有1個空格。

左花括號必須跟隨前文寫在同一行,右花括號必須在函數體後換行放置。

不能在參數和變量的左括號後和右括號前放置空格。

不能在參數和變量的逗號前放置空格,但必須在逗號後放置1個空格。

閉包參數若是有默認值,該參數必須放在參數列表末尾。

若是聲明瞭返回類型,它必須遵循普通函數和方法相同的規則;若是使用 use 關鍵字,冒號必須在 use 右括號後且冒號先後不能有空格。

閉包的聲明方式以下,留意括號,逗號,空格和花括號:

<?php

$closureWithArgs = function ($arg1, $arg2) {
    // 函數體
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // 函數體
};

$closureWithArgsVarsAndReturn = function ($arg1, $arg2) use ($var1, $var2): bool {
    // 函數體
};

參數和變量能夠分多行放置,每一個後續行縮進一次。執行此操做時,列表中的第一項必須放在下一行,而且每行只能有一個參數或變量。

結束多行列表(或者參數,變量)的時候,右括號和左大括號 必須 要放在一行,並且中間有一個空格。

下面是有和沒有多行參數列表與變量列表的閉包示例。

<?php

$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // body
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // body
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

注意格式化規則也適用一個閉包在一個方法或者操做中做爲參數被直接引用。

<?php

$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);

8. 匿名類

匿名類 必須 遵循上面章節中和閉包同樣的方針和準則。

<?php

$instance = new class {};

只要 implements 接口列表不換行,左花括號 能夠 和關鍵字 class 在同一行。若是接口列表換行,花括號 必須 放在最後一個接口的下一行。

<?php

// 花括號在同一行
$instance = new class extends \Foo implements \HandleableInterface {
    // 類內容
};

// 花括號在下一行
$instance = new class extends \Foo implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // 類內容
};
相關文章
相關標籤/搜索