
この記事では、GitHubでPR(プルリクエスト)を作成した時に、静的解析と構文チェックを自動実行して、エラー内容をレビューコメントとして吐き出す方法について紹介しています!
PHPStan + PHP_CodeSniffer + reviewdog + GitHub Actionsを導入する
今回使用するライブラリ・ツールの説明
今回使用するライブラリ・ツールは下記になります。
- PHPStan:静的解析用ライブラリ
- ide_helper:IDE補完用のヘルパーファイルを生成してくれるライブラリ
- PHP_CodeSniffer:構文チェック等を行ってくれるライブラリ
- reviewdog:ソースコードレビューを行ってくれるライブラリ
- GitHub Actions:pushやPR作成などのイベントをトリガーに、対応するアクションを組み合わせてワークフローの自動化を行うことができる
Laravel環境では、Laravel用のPHPStanとしてlarastanもあるのですが、対応しているバージョンが割と高いので、この記事では、汎用的に使えるPHPStanを用いた紹介をします。
リポジトリ:nunomaduro/larastan
PHPStanを導入する
phpstan/phpstanをinstallする
composer経由で、phpstanをinstallします。
$ composer require --dev phpstan/phpstan
リポジトリ:phpstan/phpstan
メモリが足りない場合は、COMPOSER_MEMORY_LIMITをつけて実行してあげます。
$ COMPOSER_MEMORY_LIMIT=-1 composer require --dev phpstan/phpstan

phpstanのバージョンに関しては、以下のコマンドで確認することができます!
$ ./vendor/bin/phpstan -V
PHPStanの設定ファイルを作成する
PHPStanの設定ファイルとして、phpstan.neonをプロジェクト直下に作成します。
parameters:
paths: # 検出対象のディレクトリを指定
- app # 今回はLaravelを使っているということもあり、app配下だけを検出対象に指定
level: 0 # 適用するLevel。0〜9まであり、0が最も緩い
- PHPStanの設定ファイルのドキュメントページ:Config Reference
- PHPStanのLevelについてのドキュメントページ:Rule Levels
PHPStanを実行してみる
PHPStanの設定ファイルである、phpstan.neonファイルを作成・設定したところで、PHPStanを一度実行してみます。
実行コマンドは以下(analyseは省略可能です)。
$ ./vendor/bin/phpstan analyse
メモリ不足で落ちてしまう場合は、下記のようにオプションをつけてあげます。
$ ./vendor/bin/phpstan analyse --memory-limit=1G
全く新しいシステムに対して、PHPStanを導入する場合は、エラーは発生しないかと思いますが、既存のシステムに対して、PHPStanを導入する場合は何かしらエラーが出るかと思います。
ここで、致命的なエラーが出ている場合は、後ほど作成するbaselineファイルを作成できなくなるので、修正してあげる必要があります。
致命的なエラーが出ていない場合は、一旦次のide_helperの導入に進みます。
ide_helperを導入する

Laravelを使っている場合は、ide_helperを導入してあげましょう!
ide_helperを導入せずに、PHPStanを実行すると、ファサードを使用している箇所などでエラーが発生してしまいます。
ide_helperはLaravelのIDE補完を可能にするためのものですが、今回ide_helperをインストールして、_ide_helper.phpファイルなどを用意することで、ファサード等のエラーが出なくなります。
barryvdh/laravel-ide-helperをinstallする
composer経由で、ide_helperをinstallします。
$ composer require --dev barryvdh/laravel-ide-helper
リポジトリ:barryvdh/laravel-ide-helper
使用しているLaravelのバージョンによっては、インストールに失敗するので、以下のようにバージョンを指定してあげる必要があります。
$ composer require --dev barryvdh/laravel-ide-helper:"2.8.2"
バージョン詳細:barryvdh/laravel-ide-helper/releases
config/app.phpのprovidersにIdeHelperServiceProviderクラスを追加する
barryvdh/laravel-ide-helperリポジトリのREADME.mdに記載があるように、config/app.phpのprovidersに下記を追加してあげます。
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
_ide_helper.phpファイルを生成する
IDE補完用のヘルパーファイルを生成します。
$ php artisan ide-helper:generate
プロジェクト直下に、_ide_helper.phpファイルが生成されるので、このファイルをphpstan.neonファイル内で読み取るように指定してあげます。
parameters:
paths:
- app
level: 0
scanFiles:
- _ide_helper.php # _ide_helper.phpファイルを読み取る
phpstan.neonファイルで、_ide_helper.phpファイルを読み取るように指定してあげたところで、改めてphpstanを実行してみましょう。
$ ./vendor/bin/phpstan analyse
致命的なエラーが出た場合は、その部分を修正して、致命的なエラーが出なくなるようにします。

致命的なエラーが出なければ、次に既出のエラーを無視するためのbaselineファイルを作っていきます!
baselineファイルを生成する
baselineファイルを作成することで、PHPStanを実行した際に吐かれているエラーを無視することができるようになります。
baselineファイルの作り方は以下。
$ ./vendor/bin/phpstan analyse --generate-baseline
上記を実施してあげると、プロジェクト直下にphpstan-baseline.neonファイルが作成され、このファイルに無視するエラー内容が記載されています。
これを、phpstan.neonで読み込むように設定。
includes:
- phpstan-baseline.neon # phpstan-baseline.neonファイルを読み込む
parameters:
paths:
- app
level: 0
reportUnmatchedIgnoredErrors: false # baselineファイルのエラーが発生していない場合の通知をオフにする
scanFiles:
- _ide_helper.php
この状態で、phpstanを実行すると、現時点でのエラーは起きなくなります。
仮に、baselineファイルで指定したエラー箇所を修正した場合には、エラーが発生するので、その場合は、該当箇所をbaselineファイルから削除してあげることで解消します。
PHP_CodeSnifferを導入する

続いて、構文のチェック等を行なってくれるPHP_CodeSnifferを導入していきます!
squizlabs/php_codesnifferをinstallする
composer経由で、squizlabs/php_codesnifferをinstallします。
$ composer require --dev squizlabs/php_codesniffer
リポジトリ:squizlabs/php_codesniffer
phpcsのiオプションで使用できるコーディング規約を確認する
以下のコマンドで、使用できるコーディング規約を確認することができます。
$ ./vendor/bin/phpcs -i
The installed coding standards are PEAR, Zend, PSR2, MySource, Squiz, PSR1 and PSR12

今回は、コーディング規約としてPSR-2を適用していきたいと思います
phpcs.xmlファイルを作成する
プロジェクト直下にphpcs.xmlファイルを作成して、基本となるコーディングルール等を定義していきます。
<?xml version="1.0"?>
<ruleset name="PSR2">
<description>PSR-2 coding standard</description>
<!-- 適用コーディング規約の指定 -->
<rule ref="PSR2">
<!-- 除外したい項目を列挙 -->
</rule>
<!-- 出力に色を適用 -->
<arg name="colors" />
<!-- 除外ディレクトリ -->
<exclude-pattern>./bootstrap/*</exclude-pattern>
<exclude-pattern>./database/*</exclude-pattern>
<exclude-pattern>./node_modules/*</exclude-pattern>
<exclude-pattern>./public/*</exclude-pattern>
<exclude-pattern>./storage/*</exclude-pattern>
<exclude-pattern>./tests/*</exclude-pattern>
<exclude-pattern>./vendor/*</exclude-pattern>
</ruleset>
除外ディレクトリに指定したディレクトリ以外がチェック対象となります。除外したいコーディングルールがある場合は、ruleタグ内に列挙していけばOK。
参考:squizlabs/PHP_CodeSniffer/blob/master/src/Standards/PSR2/ruleset.xml
除外したい項目については、下記のコマンドを実行することでエラー項目を列挙してくれます。
$ ./vendor/bin/phpcs -s --report=source --standard=phpcs.xml ./
書き方は以下のような感じ。
<rule ref="PSR2">
<exclude name="Squiz.WhiteSpace.SuperfluousWhitespace.EndLine"/>
</rule>
PHP_CodeSnifferを実行する
phpcs.xmlファイルにてコーディングルール等の設定を行ったので、PHP_CodeSnifferを実行してみます。
$ ./vendor/bin/phpcs --standard=phpcs.xml ./
エラーが少ない場合は、さっと修正しても良いですし、エラーが多くて修正に手間がかかる場合は一旦放置しても大丈夫です(後ほどPR単位で構文チェックしてエラーをレビューコメントとして吐くことができる方法を解説するので)。
reviewdogとGitHub Actionsを導入する
最後に、reviewdogとGitHub Actionsを導入していきます。
.github/workflows/reviewdog.ymlファイルを作成して、以下を記載します。
name: reviewdog
on: pull_request
jobs:
# 構文チェック用ジョブ(PHP_CodeSniffer + reviewdog)
lint:
runs-on: ubuntu-latest
steps:
# リポジトリからチェックアウト
- uses: actions/checkout@v2
# reviewdogをセットアップ
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
# PHP環境をセットアップ
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0' # 環境に合わせて変更してください
tools: composer:v2
# composer install
- name: Resolve dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
# 構文チェックを実行し、実行結果をreviewdogに渡す
- name: lint
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} # secrets.GITHUB_TOKENは発行せずに呼び出せる
run: ./vendor/bin/phpcs --report=emacs --standard=phpcs.xml ./ | reviewdog -reporter=github-pr-review -efm='%f:%l:%c:%m'
# 静的解析用ジョブ(PHPStan + reviewdog)
analyse:
runs-on: ubuntu-latest
steps:
# リポジトリからチェックアウト
- uses: actions/checkout@v2
# reviewdogをセットアップ
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
# PHP環境をセットアップ
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0' # 環境に合わせて変更してください
tools: composer:v2
# composer install
- name: Resolve dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
# PHPStanを実行し、実行結果をreviewdogに渡す
- name: Run PHPstan
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./vendor/bin/phpstan analyse --error-format=raw --no-progress --memory-limit=1G | reviewdog -reporter=github-pr-review -f=phpstan # PHPStan側の出力がデフォルトの--error-format=githubでは読み取れないので、--error-format=rawを指定しています

これをpushしてPRを作成すれば、reviewdog.ymlファイルに記載した、lintジョブとanalyseジョブが走ります!
仮にエラーが見つかった場合は、PRのレビューコメントとして出力されるので、確認してみてください。
下記に今回のサンプルコードを用意しています(Laravelプロジェクトはsrc配下に配置しているので、今回のものとは若干違う構成になっています)
まとめ|PHPStan+PHP_CodeSniffer+reviewdog+GitHub Actions導入
ここまで、「GitHubでPR(プルリクエスト)を作成した時に、静的解析と構文チェックを自動実行して、エラー内容をレビューコメントとして吐き出す方法」について紹介してきました。
具体的には、
- 静的解析ツールとして「PHPStan」
- 構文チェック等のツールとして「PHP_CodeSniffer」
- ソースコードレビューを行ってくれる補助ツールとして「reviewdog」
- pushやPR作成などのイベントをトリガーに、対応するアクションを組み合わせてワークフローの自動化が行える「GitHub Actions」
の設定方法について詳しく説明してきました。

まだ、これらを導入していないという方はぜひ導入してみてください!
コメント