コーディング規約(PSR-2)を守ったファイルのみcommitしよう

みなさんは普段どういったコーディング規約を採用されていますか？

私は最近までは、1人で開発することがほとんどだったので

- ハードタブでインデント
- クラス宣言と同一行にブレースを書く

```php
class Hoge {
}
```

などと結構自由にやっていましたが、複数人で開発するとなると広く浸透している[PSR-2](http://www.php-fig.org/psr/psr-2/)に慣れた方がいいであろうと思いからPSR-2を徹底しようとしている最中です。


# 公式のドキュメントとか読んで、だいたい頭に入ったけども正しくかけているか自身がない。。。

EclipseとかIDEを使用していれば、ファイル保存時にPSR-2に準拠するようなフォーマッターを自動で適用するとかできるんですが、Eclipse重いんで最近使っていないです。

まだ慣れていないのでif文の`()`の前後は半角スペースがいるんだっけ？とかよく迷ってしまいます。
その都度ググって調べるのも正直めんどくさいです。


# 自動で構文チェックを行おう

php_codesnifferを使用すれば自動で、構文チェック、構文誤りの訂正を行うことが出来ます。
今回は細かくオプションを指定していませんが、独自の規約などにも対応できるようです。詳しく知りたい方は[このあたり](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options)をご確認ください。

## インストール

今開発しているプロジェクト直下にインストールではなくグローバルでインストールしておいたほうが何かと便利だと思うので`global`オプションを付けておきます。
あとパスを通すなりalias設定するなりしておくと便利です。

```sh
composer global require "squizlabs/php_codesniffer=*"
```


## 構文チェック

適当なphpファイル。あえてPSR-2に準拠させてません。

```php:sample.php
<?php
for($i=0;$i<10;$i++){
	echo $i.PHP_EOL;
}
?>
```

チェック実施。たくさん引っかかりますね。

```sh
$ phpcs sample.php --colors --standard=PSR2

FILE: D:\sample.php
----------------------------------------------------------------------------------
FOUND 8 ERRORS AFFECTING 4 LINES
----------------------------------------------------------------------------------
 1 | ERROR | [x] End of line character is invalid; expected "\n" but found "\r\n"
 2 | ERROR | [x] Expected 1 space after FOR keyword; 0 found
 2 | ERROR | [x] Expected 1 space after first semicolon of FOR loop; 0 found
 2 | ERROR | [x] Expected 1 space after second semicolon of FOR loop; 0 found
 2 | ERROR | [x] Expected 1 space after closing parenthesis; found 0
 3 | ERROR | [x] Spaces must be used to indent lines; tabs are not allowed
 5 | ERROR | [x] A closing tag is not permitted at the end of a PHP file
 5 | ERROR | [x] Expected 1 newline at end of file; 0 found
----------------------------------------------------------------------------------
PHPCBF CAN FIX THE 8 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------

Time: 337ms; Memory: 6Mb
```

## 構文誤りの訂正

訂正実施

```sh
$ phpcbf sample.php --colors --standard=PSR2

PHPCBF RESULT SUMMARY
----------------------------------------------------------------------
FILE                                                  FIXED  REMAINING
----------------------------------------------------------------------
D:\sample.php                           8      0
----------------------------------------------------------------------
A TOTAL OF 8 ERRORS WERE FIXED IN 1 FILE
----------------------------------------------------------------------

Time: 230ms; Memory: 6Mb

```

訂正前と後を比較。diffコマンドでは違いが伝わりにくかったのでwinmergeを使って比較した様子の画像を貼っときます。

![image_20170906_173508.jpg](https://qiita-image-store.s3.amazonaws.com/0/154029/cdf1b5de-d6f7-07fb-fdd0-d6f99b07fe51.jpeg)

これでcommitしようとしているファイルがPSR-2に準拠しているかどうか簡単にチェックできるようになりました。

## commit時にphp_codesnifferを自動的に適用させたい

gitには特定のアクションをきっかけにscriptを実行させるという機能があります。
[公式ドキュメント](https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%83%95%E3%83%83%E3%82%AF)

`.git/hook/pre-commit`というファイルにscriptを書くことで、commitのタイミングで構文チェックを実施、さらに自動で訂正したりcommitを中断させたりも出来ます。

今は自分がどういった書き間違いをしているのか確認したいので、PSR-2に準拠していなければcommitを中断させるようにしています。

```sh:.git/hook/pre-commit
#!/bin/sh

if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

RETURN=0
# 拡張子がphpのものに対して実施
# 削除したファイル名に対して各コマンドを発行すると、ファイルが見つからないよとエラーになるので削除「D」は除外
for FILE in `git diff --staged --name-only --diff-filter=ACMRTUXB $against | grep "\.php$"`; do
    # シンタックスチェック
    if php -l $FILE>&/dev/null; then
        # 構文エラーが存在しない場合はphp_codesnifferで更にチェック。

        ### 訂正しないでチェックだけの場合はこっち
        # warningはスルー
        phpcs --standard=PSR2 -n $FILE>&/dev/null
        if [ $? != 0 ]; then
            echo "$FILE はPSR2に準拠していません。"
            RETURN=1
        fi
        ### 問題があれば強制的に修正する
        #phpcbf --standard=PSR2 -n $FILE>&/dev/null
        #if [ $? != 0 ]; then
        #    echo "$FILE がPSR2に準拠していなかったので修正しました。"
        #    git add $FILE
        #fi
    else
        echo "$FILEに構文エラーがあります。"
        RETURN=1
    fi
done

exit $RETURN
```