[PHP]Circle CIで変更箇所のファイルのみを静的解析(Lint)する②

# 概要

[[JavaScript]Circle CIで変更箇所のファイルのみを静的解析(Lint)する① - Qiita](https://qiita.com/mgmgOmO/items/3e30ec91d4bc9b53751d)のPHP版です。

今回導入する静的解析ツールは[PHPStan](https://github.com/phpstan/phpstan)です。
パッケージ管理ツール**composer**は設定済みとします。

結論は[コチラ](https://qiita.com/mgmgOmO/items/183cb39cc54141df8724#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E8%AA%AC%E6%98%8E)なので、既に手順が分かる人は飛ばしてください。


# 手順
## 静的解析ツール(Linter)の設定
### 1. インストール
チームで開発するためPHPStanパッケージを**ローカルインストール**します。

```bash
$ composer require --dev phpstan/phpstan
```

依存関係のエラーが起きた場合は以下を実行します。

```bash
$ composer require --dev phpstan/phpstan-shim
```

### 2. エイリアスの設定
パッケージをローカルインストールした時は、実行時のパス指定が面倒なためタスクランナーにエイリアスを登録します。
`composer.json`の`scripts`に以下のように追記します。

```composer.json
{
    "scripts": {
        "phpstan": [
            "vendor/bin/phpstan"
        ]
   }
}
```

### 3. 動作確認
以下のコマンドでLintが実行できることを確認します。

```bash
$ composer phpstan analyze path/to/file
```

**出力結果**

```
> vendor/bin/phpstan 'analyze' 'xxx.php'
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [OK] No errors                                                                 
```

## Cricle CIの設定
Circle CIとGitの連携は設定済みとします。

### 1. 設定ファイルを書く
`.circleci/config.yml`を作成し、設定を記載します。

```.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: circleci/php:7.1-cli

    steps:
      - checkout

      # Linter含むパッケージをインストールする
      - run: composer install

      # 差分のあるphpファイルのみLintを実行する
      - run: 
          name: php lint
          command: git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze       
```

### 2. 動作確認
適当な`xxx.php`を作成し、コミットしたのちにリモートにプッシュします。
ターミナルでも以下のコマンドを打ち、差分ファイルのみ表示されることを確認します。

```bash
git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php'
```

**出力結果**

```
#!/bin/bash -eo pipefail
git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze

> vendor/bin/phpstan 'analyze' 'xxx.php'
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [OK] No errors                                                                   
```

最後に、[Circle CI](https://circleci.com/)の画面でプロジェクトのジョブを確認し、Successと表示されれば成功です。

### コマンドの説明
`.circleci/config.yml`の最後のコマンドについて解説します。

```bash
git diff --name-only --diff-filter=ACMR origin/develop..origin/${CIRCLE_BRANCH} -- '*.php' | xargs -r composer phpstan analyze    
```

`git diff BRANCH1..BRANCH2`：ブランチ同士の差分を取ります。
`--name-only`：ファイル名のみを取得します。
`--diff-filter=ACMR`：A(追加)/C(コピー)/M(変更)/R(名前変更)の操作があったファイルのみを取得します。
`-- '*.php'`：対象ファイルであるphpファイルのみを取得します。
`${CIRCLE_BRANCH}`：現在の作業ブランチを取得します。
`xargs`：前のコマンドの結果を引数として後ろのコマンドに渡します。
` -r `：引数に何も結果がない場合にスキップします。(Linuxのみ)

以上です！

## 補足
私の環境の場合、`composer install`する際に`php gd`がないというエラーが起きたので、以下を`composer install`する前のステップに追記しました。

```yml
      - run:
          name: install php extension gd
          command: |
            sudo apt-get install -y libpng-dev
            sudo docker-php-ext-install gd
```

[Installing php7.1-gd on the php:7.1.4-apache container - Build Environment - CircleCI Discuss](
https://discuss.circleci.com/t/installing-php7-1-gd-on-the-php-7-1-4-apache-container/14570)

## 参考
[[PHP] 静的解析ツールPHPStanの機能概要 - Qiita](https://qiita.com/qiita_masaharu/items/24bf34579119628eefe2)
[PHPStanで始めるPHPのための静的解析 #phperkaigi - Mercari Engineering Blog](https://tech.mercari.com/entry/phpstan)
[ピクシブ百科事典に静的解析のCIを導入した話 - pixiv inside](https://inside.pixiv.blog/mdan/7037)

## 最後に
Linterの設定をそれぞれPHPとJSに対して行ったので、個人的にはcomposerとnpmの対応する機能が理解できた気がします。
記事に間違いや不明な点があれば遠慮なくご指摘ください。