跳到內容

程式碼標準

編輯此頁面

Symfony 程式碼是由世界各地成千上萬的開發人員貢獻的。為了使每段程式碼看起來和感覺起來都很熟悉,Symfony 定義了一些所有貢獻都必須遵循的程式碼標準。

這些 Symfony 程式碼標準基於 PSR-1PSR-2PSR-4PSR-12 標準,因此您可能已經了解其中大部分標準。

使您的程式碼遵循程式碼標準

Symfony 並非手動審查您的程式碼,而是讓確保您貢獻的程式碼符合預期的程式碼語法變得簡單。首先,安裝 PHP CS Fixer tool,然後執行此命令以修正任何問題

1
2
$ cd your-project/
$ php php-cs-fixer.phar fix -v

如果您忘記執行此命令並提出包含任何語法問題的 pull request,我們的自動化工具會警告您並提供解決方案。

Symfony 程式碼標準詳解

如果您想詳細了解 Symfony 程式碼標準,以下是一個簡短範例,其中包含以下描述的大部分功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Acme;

use Other\Qux;

/**
 * Coding standards demonstration.
 */
class FooBar
{
    public const SOME_CONST = 42;

    private string $fooBar;

    /**
     * @param $dummy some argument description
     */
    public function __construct(
        string $dummy,
        private Qux $qux,
    ) {
        $this->fooBar = $this->transformText($dummy);
    }

    /**
     * @deprecated
     */
    public function someDeprecatedMethod(): string
    {
        trigger_deprecation('symfony/package-name', '5.1', 'The %s() method is deprecated, use Acme\Baz::someMethod() instead.', __METHOD__);

        return Baz::someMethod();
    }

    /**
     * Transforms the input given as the first argument.
     *
     * @param $options an options collection to be used within the transformation
     *
     * @throws \RuntimeException when an invalid option is provided
     */
    private function transformText(bool|string $dummy, array $options = []): ?string
    {
        $defaultOptions = [
            'some_default' => 'values',
            'another_default' => 'more values',
        ];

        foreach ($options as $name => $value) {
            if (!array_key_exists($name, $defaultOptions)) {
                throw new \RuntimeException(sprintf('Unrecognized option "%s"', $name));
            }
        }

        $mergedOptions = array_merge($defaultOptions, $options);

        if (true === $dummy) {
            return 'something';
        }

        if (\is_string($dummy)) {
            if ('values' === $mergedOptions['some_default']) {
                return substr($dummy, 0, 5);
            }

            return ucwords($dummy);
        }

        return null;
    }

    /**
     * Performs some basic operations for a given value.
     */
    private function performOperations(mixed $value = null, bool $theSwitch = false): void
    {
        if (!$theSwitch) {
            return;
        }

        $this->qux->doFoo($value);
        $this->qux->doBar($value);
    }
}

結構

  • 在每個逗號分隔符後新增一個空格;
  • 在二元運算子 (==&&、...) 周圍新增一個空格,串聯 (.) 運算子除外;
  • 將一元運算子 (!--、...) 放在受影響變數的旁邊;
  • 除非您需要型別轉換,否則一律使用完全相同的比較
  • 當檢查變數是否符合運算式時,請使用 尤達條件式,以避免在條件陳述式內發生意外的賦值 (這適用於 ==!====!==);
  • 在多行陣列中,即使是最後一個項目之後,也要在每個陣列項目之後新增逗號;
  • return 陳述式之前新增一個空行,除非 return 單獨位於陳述式群組內 (例如 if 陳述式);
  • 當函式明確傳回 null 值時,請使用 return null;,當函式傳回 void 值時,請使用 return;
  • 請勿將 void 傳回型別新增至測試中的方法;
  • 無論控制結構主體包含的陳述式數量為何,都請使用大括號來表示;
  • 每個檔案定義一個類別 - 這不適用於不打算從外部執行個體化,因此不受 PSR-0PSR-4 自動載入標準影響的私有輔助類別;
  • 在與類別名稱相同的行上宣告類別繼承和所有實作的介面;
  • 在方法之前宣告類別屬性;
  • 先宣告公用方法,然後宣告受保護的方法,最後宣告私有方法。此規則的例外情況是類別建構子和 PHPUnit 測試的 setUp()tearDown() 方法,這些方法必須永遠是第一個方法,以提高可讀性;
  • 將所有引數宣告在與方法/函式名稱相同的行上,無論引數數量為何。唯一的例外是使用 建構子屬性提升的建構子方法,其中每個參數都必須在新行上,並加上尾隨逗號
  • 無論建構子有多少引數,在執行個體化類別時都請使用括號;
  • 例外和錯誤訊息字串必須使用 sprintf 串聯;
  • 例外和錯誤訊息不得包含反引號,即使在參考技術元素 (例如方法或變數名稱) 時也是如此。必須隨時使用雙引號

    1
    2
    - Expected `foo` option to be one of ...
    + Expected "foo" option to be one of ...
  • 例外和錯誤訊息必須以大寫字母開頭,並以句點 . 結尾;
  • 包含類別名稱的例外、錯誤和棄用訊息必須使用 get_debug_type() 而不是 ::class 來擷取它

    1
    2
    - throw new \Exception(sprintf('Command "%s" failed.', $command::class));
    + throw new \Exception(sprintf('Command "%s" failed.', get_debug_type($command)));
  • 在傳回或擲回某些內容的 ifcase 條件之後,請勿使用 elseelseifbreak
  • 請勿在 [ 偏移存取器周圍和 ] 偏移存取器之前使用空格;
  • 為每個不屬於全域命名空間的類別新增 use 陳述式;
  • 當 PHPDoc 標籤 (例如 @param@return) 包含 null 和其他型別時,請務必將 null 放在型別清單的末尾。

命名慣例

  • 針對 PHP 變數、函式和方法名稱、引數使用 camelCase (例如 $acceptableContentTypeshasSession());
針對組態參數、路由名稱和 Twig 範本變數使用 snake_case
變數 (例如 framework.csrf_protectionhttp_status_code);
  • 針對常數使用 SCREAMING_SNAKE_CASE (例如 InputArgument::IS_ARRAY);
  • 針對列舉案例使用 UpperCamelCase (例如 InputArgumentMode::IsArray);
  • 針對所有 PHP 類別、介面、特徵和列舉使用命名空間,並針對其名稱使用 UpperCamelCase (例如 ConsoleLogger);
  • 除了 PHPUnit *TestCase 之外,所有抽象類別都加上 Abstract 前綴。請注意,某些早期的 Symfony 類別不遵循此慣例,且基於回溯相容性原因而未重新命名。但是,所有新的抽象類別都必須遵循此命名慣例;
  • 介面加上 Interface 後綴;
  • 特徵加上 Trait 後綴;
  • 請勿針對類別或列舉使用專用的後綴 (例如 ClassEnum),但以下列出的情況除外。
  • 例外狀況加上 Exception 後綴;
  • 與服務組態相關的 PHP 屬性加上 As 前綴 (例如 #[AsCommand]#[AsEventListener] 等);
  • 與控制器引數相關的 PHP 屬性加上 Map 前綴 (例如 #[MapEntity]#[MapCurrentUser] 等);
  • 針對 PHP 檔案命名使用 UpperCamelCase (例如 EnvVarProcessor.php),針對 Twig 範本和 Web 資產命名使用 snake case (section_layout.html.twigindex.scss);
  • 對於 PHPDoc 和轉型中的型別提示,請使用 bool (而不是 booleanBoolean)、int (而不是 integer)、float (而不是 doublereal);
  • 別忘了查看更詳細的 慣例 文件,以取得更多主觀的命名考量。

服務命名慣例

  • 服務名稱必須與其類別的完整類別名稱 (FQCN) 相同 (例如 App\EventSubscriber\UserSubscriber);
  • 如果同一個類別有多個服務,請針對主要服務使用 FQCN,並針對其餘服務使用小寫和底線名稱。您可以選擇將它們分成以點分隔的群組 (例如 something.service_namefos_user.something.service_name);
  • 針對參數名稱使用小寫字母 (除非使用 %env(VARIABLE_NAME)% 語法參考環境變數);
  • 為公用服務新增類別別名 (例如,將 Symfony\Component\Something\ClassName 別名為 something.service_name)。

文件

  • 只有在 PHPDoc 區塊新增與名稱、原生型別宣告或內容不重複的相關資訊 (例如 instanceof 檢查) 時,才為類別、方法和函式新增 PHPDoc 區塊;
  • 僅使用 PHPDoc 參考中定義的註解和型別。為了改善靜態分析的型別,也允許使用下列註解

  • 將註解分組在一起,使相同型別的註解緊接在彼此之後,而不同型別的註解則以單一空行分隔;
  • 如果方法未傳回任何內容,請省略 @return 註解;
  • 請勿在類別、方法和函式上使用單行 PHPDoc 區塊,即使它們只包含一個註解 (例如,請勿將 /** {@inheritdoc} */ 放在單行中);
  • 在新增類別或對現有類別進行重大變更時,可以新增或展開包含個人聯絡資訊的 @author 標籤。請注意,可以根據向 核心團隊 提出的要求更新或移除個人聯絡資訊。

許可證

  • Symfony 是在 MIT 許可證下發布的,且許可證區塊必須出現在每個 PHP 檔案的頂端,在命名空間之前。
本作品 (包括程式碼範例) 已根據 創用 CC BY-SA 3.0 許可證授權。
目錄
    版本