Visual Studio Code 的 PHP CS Fixer 設定

最近有幸換一台好一點電腦,開始投入 VSCode 的懷抱,轉換總是陣痛一波波襲來,於是趕緊記錄下來。希望能對以後使用 VSCode 的 PHPer 排版有幫助。

PHP CS Fixer 是一個自動格式化 PHP 程式碼,利用這個外掛達到達到 PHP 統一風格的效果。


版本:

PHP CS Fixer 3.73.1 Persian Successor by Fabien Potencier, Dariusz Ruminski and contributors.

PHP runtime: 8.2.28


PHP CS Fixer 安裝與設定

1. 安裝 PHP CS Fixer

你有兩種主要安裝方式:透過 Composer 全域安裝或下載 phar 檔案。以下以 Composer 全域安裝為例:

1. 確保 Composer 已安裝

如果尚未安裝 Composer,請至 Composer 官方網站 下載並安裝。

2. 全域安裝 PHP CS Fixer

開啟終端機(Terminal),執行下列指令:

composer global require friendsofphp/php-cs-fixer

安裝完成後,透過以下指令確認執行檔路徑:

composer global config bin-dir --absolute

例如,你可能會得到 /Users/yourname/.composer/vendor/bin。記下這個路徑,因為稍後在 VSCode 或命令列使用時需要指定。

注意兩點:

  1. 注意 Composer / PHP 的路徑和權限。可能會遇到執行權限不足的問題。
  2. 注意 User 的路徑名稱,這邊統一用 yourname 代替。

2. 建立 PHP CS Fixer 設定檔

我們提供以下最新版的 config.php 設定檔範例,此檔案包含多項格式化規則(例如 PSR、Symfony 規範),並採用新版語法。請將此檔案存放在你希望統一管理格式化規則的位置,例如 ~/.config/php-cs-fixer/config.php。

小提醒,註解我是用 AI 生成的。裡面設定得依照需求和團隊規範來調整。

<?php

$header = <<<'EOF'
This file is part of PHP CS Fixer.

(c) Fabien Potencier <[email protected]>
    Dariusz Rumiński <[email protected]>

This source file is subject to the MIT license that is bundled
with this source code in the file LICENSE.
EOF;

$finder = PhpCsFixer\Finder::create()
    ->exclude('tests/Fixtures') // 排除特定目錄
    ->in(__DIR__) // 設定要檢查的目錄
;

$config = (new PhpCsFixer\Config())
    ->setRiskyAllowed(true) // 允許使用可能具有風險的規則
    ->setRules([
        // '@PHP56Migration' => true, // PHP 5.6 的語法遷移規則集(已註解掉)
        '@PHPUnit60Migration:risky'   => true, // 適用於 PHPUnit 6.0 的遷移規則(風險規則)
        '@PSR1'                       => true, // 遵循 PSR-1 基本編碼標準
        '@PSR2'                       => true, // 遵循 PSR-2 編碼風格指南
        '@Symfony'                    => true, // 遵循 Symfony 的編碼標準
        '@Symfony:risky'              => true, // Symfony 的風險規則集
        'align_multiline_comment'     => true, // 將多行註解對齊
        'array_indentation'           => true, // 陣列的縮排規則
        'array_syntax'                => ['syntax' => 'short'], // 使用短陣列語法
        'blank_line_before_statement' => true, // 在特定語句前插入空行
        'binary_operator_spaces'      => [ // 二元運算符的空格規則
            'operators' => [
                '=>' => 'align', // 將 `=>` 對齊
                '='  => 'single_space', // `=` 使用單一空格
            ],
        ],
        'combine_consecutive_issets'   => true, // 合併連續的 `isset` 語句
        'combine_consecutive_unsets'   => true, // 合併連續的 `unset` 語句
        'comment_to_phpdoc'            => true, // 將普通註解轉換為 PHPDoc
        'compact_nullable_typehint'    => true, // 使用緊湊的 nullable 類型提示語法
        'concat_space'                 => ['spacing' => 'one'], // 字串連接符號使用單一空格
        'escape_implicit_backslashes'  => true, // 轉義隱式的反斜線
        'explicit_indirect_variable'   => true, // 明確的間接變數語法
        'explicit_string_variable'     => true, // 明確的字串變數語法
        'final_internal_class'         => true, // 將內部類標記為 final
        'fully_qualified_strict_types' => true, // 使用完全限定的類型名稱
        'function_to_constant'         => ['functions' => ['get_class', 'get_called_class', 'php_sapi_name', 'phpversion', 'pi']], // 將特定函數轉換為常數
        // 'header_comment' => ['header' => $header], // 添加檔案頭部註解(已註解掉)
        'heredoc_to_nowdoc'                             => true, // 將 heredoc 轉換為 nowdoc
        'increment_style'                               => false, // 遞增/遞減運算符的風格
        'list_syntax'                                   => ['syntax' => 'short'], // 使用短語法的 list
        'logical_operators'                             => true, // 使用邏輯運算符 `and`, `or`, `xor` 替代符號
        'method_argument_space'                         => ['on_multiline' => 'ensure_fully_multiline'], // 方法參數的空格規則
        'method_chaining_indentation'                   => true, // 方法鏈式調用的縮排
        'multiline_comment_opening_closing'             => true, // 多行註解的開頭和結尾格式化
        'no_alternative_syntax'                         => true, // 禁用替代語法(如 `endif`)
        'no_binary_string'                              => true, // 禁用二進位字串語法
        'no_extra_blank_lines'                          => ['tokens' => ['break', 'continue', 'extra', 'return', 'throw', 'use', 'parenthesis_brace_block', 'square_brace_block', 'curly_brace_block']], // 移除多餘的空行
        'no_null_property_initialization'               => true, // 移除屬性初始化為 null
        'echo_tag_syntax'                               => ['format' => 'long'], // 使用長格式的 echo 標籤
        'no_superfluous_elseif'                         => true, // 移除多餘的 elseif
        'no_unneeded_curly_braces'                      => true, // 移除不必要的大括號
        'no_unneeded_final_method'                      => true, // 移除不必要的 final 方法
        'no_unreachable_default_argument_value'         => true, // 移除無法到達的默認參數值
        'no_unset_on_property'                          => true, // 禁止對屬性使用 unset
        'no_useless_else'                               => true, // 移除無用的 else
        'no_useless_return'                             => true, // 移除無用的 return
        'ordered_class_elements'                        => true, // 排序類的元素
        'ordered_imports'                               => true, // 排序 import 語句
        'php_unit_internal_class'                       => true, // PHPUnit 的內部類應標記為 final
        'phpdoc_order_by_value'                         => ['annotations' => ['covers']], // 按值排序 PHPDoc 的註解
        'php_unit_set_up_tear_down_visibility'          => true, // 設置 PHPUnit 的 setUp/tearDown 方法的可見性
        'php_unit_strict'                               => true, // 使用 PHPUnit 的嚴格模式
        'php_unit_test_annotation'                      => true, // 強制使用 PHPUnit 的 @test 註解
        'php_unit_test_case_static_method_calls'        => ['call_type' => 'this'], // 使用 `$this` 調用靜態方法
        'php_unit_test_class_requires_covers'           => true, // 強制測試類需要 @covers 註解
        'phpdoc_add_missing_param_annotation'           => true, // 添加缺失的 @param 註解
        'phpdoc_order'                                  => true, // 排序 PHPDoc 的標籤
        'phpdoc_trim_consecutive_blank_line_separation' => true, // 修剪 PHPDoc 中的連續空行
        'phpdoc_types_order'                            => true, // PHPDoc 類型排序
        'return_assignment'                             => false, // 避免直接返回賦值
        'semicolon_after_instruction'                   => true, // 在指令後添加分號
        'single_line_comment_style'                     => true, // 單行註解的風格
        'strict_comparison'                             => false, // 使用嚴格比較
        'strict_param'                                  => false, // 使用嚴格參數
        'string_line_ending'                            => true, // 字串行結尾一致
        'ternary_operator_spaces'                       => true, // 三元運算符的空格規則
        'trim_array_spaces'                             => true, // 修剪陣列中的多餘空格
        'unary_operator_spaces'                         => true, // 一元運算符的空格規則
        'yoda_style'                                    => true, // 使用 Yoda 條件風格
        'whitespace_after_comma_in_array'               => true, // 陣列中逗號後的空格
    ])
    ->setFinder($finder)
;

// special handling of fabbot.io service if it's using too old PHP CS Fixer version
if (false !== getenv('FABBOT_IO')) {
    try {
        PhpCsFixer\FixerFactory::create()
            ->registerBuiltInFixers()
            ->registerCustomFixers($config->getCustomFixers())
            ->useRuleSet(new PhpCsFixer\RuleSet($config->getRules()));
    } catch (PhpCsFixer\ConfigurationException\InvalidConfigurationException $e) {
        $config->setRules([]);
    } catch (UnexpectedValueException $e) {
        $config->setRules([]);
    } catch (InvalidArgumentException $e) {
        $config->setRules([]);
    }
}

return $config;

3. 配置與使用

(1) 測試設定檔是否正常運作

在終端機中執行以下指令,檢查格式化是否能正常運作:

php-cs-fixer fix --config=/Users/yourname/.config/php-cs-fixer/config.php --dry-run --diff

若顯示格式化差異且無錯誤訊息,代表設定檔運作正常。

(2) 在 VSCode 中整合使用

若你在 VSCode 中進行開發,請依下列步驟進行設定:

1. 安裝 VSCode PHP CS Fixer 擴充套件

可從 VSCode 擴充功能市場搜尋並安裝例如 junstyle.php-cs-fixer 之類的擴充套件。

2. 設定 VSCode 使用全域 PHP CS Fixer

在 VSCode 的 settings.json 中加入下列設定,指定執行檔路徑與全域設定檔位置:

{
    "php-cs-fixer.executablePath": "/Users/yourname/.composer/vendor/bin/php-cs-fixer",
    "php-cs-fixer.config": "/Users/yourname/.config/php-cs-fixer/config.php",
    "editor.formatOnSave": true,
    "[php]": {
        "editor.defaultFormatter": "junstyle.php-cs-fixer"
    }
}

※ 請依據實際路徑修改 “php-cs-fixer.executablePath” 的內容。

3. 測試 VSCode 格式化功能

開啟一個 PHP 檔案,嘗試保存(Save),檢查程式碼是否依照設定自動格式化。

4. 設定檔內容說明

這份設定檔主要包含以下部分:

Header 字串:定義了版權和授權說明,雖然目前透過 header_comment 規則被註解掉,但可根據需求啟用。

Finder 設定:透過 PhpCsFixer\Finder 指定排除某些目錄(例如 tests/Fixtures),並指定掃描路徑(使用 __DIR__)。

Config 物件:利用 (new PhpCsFixer\Config()) 建立設定物件,並透過 setRules 指定各項格式化規則,例如 PSR、Symfony、單行註解、縮排、運算子對齊等。

特別注意:

• 將原本已被移除的規則集(如 @PHP56Migration)註解掉。

• 對於已重命名的規則,例如 no_short_echo_tag 改為 echo_tag_syntax,並依新規範提供相應配置。

• binary_operator_spaces 的設定改為使用 operators 陣列,設定 => 為 align,而 = 為 single_space。

特殊處理:針對 fabbot.io 等可能使用較舊版 PHP CS Fixer 的服務,透過 try/catch 機制進行相容性處理。


總結

按照以上步驟完成安裝、設定檔建立及 VSCode 整合後,你就能使用這份統一的 PHP CS Fixer 設定來自動格式化 PHP 程式碼,確保程式碼風格的一致性與可讀性。若有需要進一步調整規則,可以參考 PHP CS Fixer 官方文件 進行自訂。


已發佈

分類:

作者:

標籤: