使用PHPCS+GIT鉤子保障團隊開發中代碼風格一致性實踐
來自專欄 PHP技術大全8 人贊了文章
一、背景
筆者在6月份加入新團隊,新團隊這邊剛組建起來,基礎一些東西還處於待完善狀態,比如筆者組內同學約定使用PSR-2的編碼風格規範,但是並不是所有人都嚴格按照PSR-2來提交代碼。
最大的原因就是口頭的約束力極為有限,而團隊中大家使用的編輯器不統一,有使用phpstorm,也有使用VS Code更有vim,而各種編輯器都有自己的格式化規則,因此代碼風格統一是個問題;
具體一點來說,當張三使用VS Code提交了一個代碼文件,李四pull代碼之後使用phpstorm進行格式化後再提交,代碼風格發生變化提交到伺服器,張三再pull代碼,使用VS Code格式化,代碼又一次發生變化;這樣反反覆復的改變,開發同學會覺得麻煩,代碼審計同學也同樣麻煩;
在筆者上家公司的技術團隊,會由架構組來處理類似的問題,於是這裡筆者把上一個團隊實現的方式照搬過來,同樣在git的鉤子上做文章,如果有人的代碼不符合psr-2代碼風格規範,通過git鉤子將不其commit,並且給出具體行號和具體的原因,更方便的是提供一個快速格式化的命令。
二、實現概要
- 安裝php-cs
- 配置php-cs
- 集成到編輯器
- git觸發檢測
三、安裝PHP-CS
php-cs可以用來檢測代碼是否符合PSR-2規範,同時支持對不符合規範的代碼自動格式化,讓其轉成PSR-2的編碼風格。
3.1 安裝composer
php-cs依賴於composer,所以筆者需要先安裝composer,安裝的方法有很多種,這裡提供mac操作系統下兩種安裝方法
brew安裝composer命令為:
brew install composer
手動安裝composer命令為:
wget https://getcomposer.org/download/1.7.1/composer.phar && chmod 777 composer.phar && mv composer.phar /usr/local/bin/composer
3.2 安裝PHP-CS
安裝好composer之後,可以用composer快速安裝php-cs,安裝命令如下
composer global require "squizlabs/php_codesniffer=*"
當命令執行完成之後,會在筆者當前用戶的主目錄下創建一個 .composer 目錄,在目錄中包含了筆者需要的php-cs,此時筆者可以執行下方命令來驗證是否安裝成功
~/.composer/vendor/bin/phpcs --help
當命令執行後,如果能看到下方的一些信息,那麼就代表安裝成功
- Check STDIN instead of local files and directories -n Do not print warnings (shortcut for --warning-severity=0) -w Print both warnings and errors (this is the default) -l Local directory only, no recursion -s Show sniff codes in all reports -a Run interactively -e Explain a standard by showing the sniffs it includes -p Show progress of the run -q Quiet mode; disables progress and verbose output -m Stop error messages from being recorded (saves a lot of memory, but stops many reports from being used) -v Print processed files -vv Print ruleset and token output -vvv Print sniff processing information -i Show a list of installed coding standards -d Set the [key] php.ini value to [value] or [true] if value is omitted
3.3 全局使用
前面筆者使用驗證的命令的路徑太長,後續如果要使用是極為不方便的,所以筆者需要將這寫路徑加入到全局中,加入的命令如下
ln -s ~/.composer/vendor/bin/phpcs /usr/local/bin/phpcsln -s ~/.composer/vendor/bin/phpcbf /usr/local/bin/phpcbf
當執行完成之後,可以使用短命令來驗證是否加入全局成功,可以用下方的命令
phpcs --help
執行成功之後,返回結果應該和上方完整路徑返回的一致。
3.4 設置默認標準
phpcs默認的編碼格式並不是php-cs,所以當不指定標準的時候,檢測的結果並不準確,但每次都手動指定也挺麻煩,所以筆者可以設置一個默認標準,命令如下:
phpcs --config-set default_standard PSR2phpcbf --config-set default_standard PSR2
3.5 PHPCS檢測
現在筆者可以用phpcs來真實的試驗了,筆者先準備一個PHP文件,文件裡面的內容如下代碼示例,可以看出這份代碼並不符合PSR-2的風格規範
<?phpfunction test_test(){ echo daxia;}test();
通過PHP-CS檢測編碼風格,命令如下
phpcs /Users/tangqingsong/mycode/test.php
命令執行完成之後,可以看到如下代碼提示,在提示中筆者能看到具體哪一行,提示級別,以及具體的提示原因
FILE: /Users/song/mycode/test.php-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------FOUND 2 ERRORS AND 1 WARNING AFFECTING 3 LINES------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 | WARNING | [ ] A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is | | defined on line 3 and the first side effect is on line 8. 3 | ERROR | [x] Opening brace should be on a new line 8 | ERROR | [x] Expected 1 newline at end of file; 0 found-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Time: 79ms; Memory: 4Mb
3.6 PHPCS檢測
自動格式化編碼風格命令
phpcbf /Users/tangqingsong/mycode/test.php
命令執行完成之後,可以看到如下返回提示,處理了哪一些文件,以及類型
PHPCBF RESULT SUMMARY----------------------------------------------------------------------FILE FIXED REMAINING----------------------------------------------------------------------/Users/song/mycode/test.php 2 1----------------------------------------------------------------------A TOTAL OF 2 ERRORS WERE FIXED IN 1 FILE----------------------------------------------------------------------Time: 68ms; Memory: 4Mb
再次使用PHP-CS檢測
phpcs /Users/tangqingsong/mycode/test.php
執行完成之後,通過命令再次查看結果
FILE: /Users/song/mycode/test.php----------------------------------------------------------------------------------------------------------------------------------------------FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE---------------------------------------------------------------------------------------------------------------------------------------------- 1 | WARNING | A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute | | logic with side effects, but should not do both. The first symbol is defined on line 3 and the first side effect is on line 9.----------------------------------------------------------------------------------------------------------------------------------------------Time: 71ms; Memory: 4Mb
能看到最開始檢測有三次不合格,但現在只剩下一處了;這裡說一下為什麼phpcbf沒有幫完全處理呢,因為phpcbf只能處理代碼風格等方式,而不能幫你處理裡面的命名與代碼實現規則,所以有少部分還需要人為去更正,但並不會太多。
四、編輯器編輯與配置
很少開發者只使用終端就開發代碼,通常都會用到編輯器,因此筆者也需要把phpcs和編輯器進行結合
4.1 讓編輯器使用PSR-2標準
- 設置->code style -> PHP 中選擇風格為 psr1/2
2. 設置->languages->php->code sniffer 中設置phpcs的路徑
3. 設置->Editor->Inspections展開點擊右側的PHP,勾選下面的兩個PHP,選擇使用PSR2
下面還有一處,也要選中
現在筆者使用phpstorm的格式化,將會自動格式化成psr-2的風格。
4.2 集成phpcs
經過上面的操作,phpstorm代碼格式化的規則基本與phpcs的規則基本一致了,但也有一小部分不一致,所以後面還要用到phpcs和phpcbf。
筆者如果每次都在終端去執行phpcs風格檢測花費時間可不少,為了提高工作效率,可以在phpstorm集成phpcs檢測規範的功能,設置路徑:Tools->External Tools->添加-> (/usr/local/bin/phpcs ) ($FileDir$/$FileName$)
4.3 集成phpcbf
如果每次都在終端去執行phpcbf格式化,還是會有一些麻煩,所以筆者也可以在phpstorm集成phpcbf自動格式化功能,設置路徑:Tools->External Tools->添加-> (/usr/local/bin/phpcbf ) ($FileDir$/$FileName$)
五、GIT配置篇
當前面一切準備就緒,筆者就可以在git鉤子裡面增加強制的策略了,git鉤子腳本存放於項目下 .git/hooks/ 文件夾下,按照下面的步驟筆者來添加一個commit事件。
5.1 新增鉤子文件
在你的項目根目錄下,使用vim命令或其他方式,新增一個文件 ./.git/hooks/pre-commit,然後把下面的腳本放進去,之後再保存。
#!/bin/shPHPCS_BIN=/usr/local/bin/phpcsPHPCS_CODING_STANDARD=PSR2PHPCS_FILE_PATTERN=".(php)$"FILES=$(git diff HEAD^..HEAD --stat)if [ "$FILES" == "" ]; then exit 0fifor FILE in $FILESdo echo "$FILE" | egrep -q "$PHPCS_FILE_PATTERN" RETVAL=$? if [ "$RETVAL" -eq "0" ] then PHPCS_OUTPUT=$($PHPCS_BIN --standard=$PHPCS_CODING_STANDARD $FILE) PHPCS_RETVAL=$? if [ $PHPCS_RETVAL -ne 0 ]; then echo $PHPCS_OUTPUT exit 1 fi fidoneexit 0
需要注意的是讓這個文件有可執行許可權,最直接的辦法就是設置為777,參考命令如下:
chmod 777 .git/hooks/pre-commit
5.2 本地鉤子
現在筆者故意讓php代碼風格不一致,然後使用git commit來提交,看看git是否會阻止提交,以下面這份代碼為例
<?phpfunction test_test(){ echo daxia;}test();
可以很明顯的看出來,這份代碼沒有按照駝峰命名法,大括弧也沒用換行的兩處問題;把它保存在根目錄名為test.php文件,然後執行git commit命令,如下
git add test.php && git commit . -m test
命令執行後,git返回了如下信息,便終止了
FILE: /Users/song/mycode/work/xiaoyu/test.php----------------------------------------------------------------------------------------------------------------------------------------------FOUND 2 ERRORS AND 1 WARNING AFFECTING 3 LINES---------------------------------------------------------------------------------------------------------------------------------------------- 1 | WARNING | [ ] A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should | | execute logic with side effects, but should not do both. The first symbol is defined on line 3 and the first side effect | | is on line 8. 3 | ERROR | [x] Opening brace should be on a new line 8 | ERROR | [x] Expected 1 newline at end of file; 0 found----------------------------------------------------------------------------------------------------------------------------------------------PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY----------------------------------------------------------------------------------------------------------------------------------------------Time: 63ms; Memory: 4Mb
驗證一下git是否commit成功,可以執行下面的命令:
git status
返回結果如下
位於分支 develop您的分支與上游分支 origin/develop 一致。要提交的變更: (使用 "git reset HEAD <文件>..." 以取消暫存) 新文件: test.php
說明筆者前面的命令只成功執行了 git add . 而後面commit則成功阻擋了。
5.3 服務端鉤子
前面一個步驟筆者已經成功的在本地的commit鉤子中阻擋了觸發,但是任然有可能有夥伴會繞過,或者新項目沒有部署等,導致可以最終提交上來的代碼還是存在不符合psr-2風格,所以這個時候筆者就需要在服務端的push事件做一些處理。
這個時候筆者需要在伺服器的鉤子事件中新增一個,pre-receive 文件。
在服務端去配置的時候遇到了幾個坑,後來筆者放棄了,有興趣的可以留言或私信。
作者:湯青松
微信:songboy8888
推薦閱讀: