使用 Git pre-commit 自動修正 PHP 的 Coding Style

在 VS Code 下,除了[使用 extension - junstyle.php-cs-fixer 進行 PHP 的 Coding Style 修正] 1 之外,也可以使用 [Git hooks] 2 的功能,在 commit 之前執行指定的 script,稱為 [pre-commit] 3,搭配 [php-cs-fixer] 4 就能自動化的對有差異的 PHP 檔案進行 Coding Style 的修正。

環境

  1. macOS 10.13.6 High Sierra
  2. PHP 7.3.5

開始設定 pre-commit

Step 1. 檢查是否有 hooks 目錄

檢查 workspace 下的 .git 目錄是否有 hooks 子目錄,如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ll ./.git
total 64
-rw-r--r-- 1 jerryhuang staff 8B May 17 18:02 COMMIT_EDITMSG
-rw-r--r-- 1 jerryhuang staff 0B May 19 12:54 FETCH_HEAD
-rw-r--r-- 1 jerryhuang staff 24B May 17 17:23 HEAD
-rw-r--r-- 1 jerryhuang staff 371B May 17 17:30 config
-rw-r--r-- 1 jerryhuang staff 73B May 17 17:30 description
drwxr-xr-x 14 jerryhuang staff 448B May 17 17:59 hooks
-rw-r--r-- 1 jerryhuang staff 11K May 17 18:02 index
drwxr-xr-x 3 jerryhuang staff 96B May 17 17:30 info
drwxr-xr-x 4 jerryhuang staff 128B May 7 12:15 logs
drwxr-xr-x 143 jerryhuang staff 4.5K May 17 18:02 objects
drwxr-xr-x 5 jerryhuang staff 160B May 7 12:16 refs
-rw-r--r--@ 1 jerryhuang staff 174B May 17 18:07 sourcetreeconfig

如果有 hooks,則跳過 Step 2。

Step 2. 建立 hooks 目錄

同樣地在 workspace 目錄下,執行

1
$ git init

此時會重新建立 git 及其子目錄 hooks 與該目錄內的 sample 檔案。

Step 3. 新增 pre-commit 檔案內容

在 workspace 下執行 vim ./.git/hooks/pre-commit,新增如下的檔案內容

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
#!/bin/bash

pass=true

files=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(php|phtml)$')
if [ "$files" != "" ]; then

# Run php syntax check before commit
while read -r file; do
php -l "$file"
if [ $? -ne 0 ]; then
pass=false
fi
done <<< "$files"

# Run php-cs-fixer validation before commit
echo "$files" | xargs ./vendor/bin/php-cs-fixer fix --diff --config .php_cs
if [ $? -ne 0 ]; then
pass=false
fi

# Automatically add files that may have been fixed by php-cs-fixer
echo "$files" | xargs git add
fi

if $pass; then
exit 0
else
echo ""
echo "PRE-COMMIT HOOK FAILED:"
echo "Code style validation failed. Please fix errors and try committing again."
exit 1
fi

請留意 echo "$files" | xargs ./vendor/bin/php-cs-fixer fix --diff --config .php_cs 這段,

  1. ./vendor/bin/php-cs-fixer: 是使用 composer require --dev friendsofphp/php-cs-fixer 安裝在 project 內 vendor 目錄中的 php-cs-fixer 進行 Coding Style 修正。Global 安裝方式請參考 [FriendsOfPHP/PHP-CS-Fixer] 6
  2. .php_cs: 使用 [在 vs code 使用 php cs fixer 進行 coding style 的格式修正] 1 一文內建立的檔案,或參考 [FriendsOfPHP/PHP-CS-Fixer] 6 內的 .php_cs.dist 再依據需求修改。

Step 4. 修改 pre-commit 的權限

1
$ chmod +x .git/hooks/pre-commit

必須修改 pre-commit 的權限,這樣才能在 commit 前正確執行寫 php-cs-fixer。

完成以上設定後,每次在 commit 前,只要有產生差異的 PHP 檔案,就會自動進行 Coding Style 修正。

參考資料 References

  • [Automating Code Style Fixes with Git and PHP Coding Standards Fixer] 5