LaravelにPHPの静的解析ツールを導入し、コードをきれいに保つ
IT技術
LaravelにPHPの静的解析ツールを導入し、コードをきれいに保つ
今回は、PHP(Laravel)にフォーカスを当てた話となります。
コーディングにはコーディング規約というものが存在し、それに基づいて開発することで、きれいなコードを保つことができます。
多くのエンジニアさんは、コーディング規約に則っているかどうかのチェックツールや、コーディング規約に則るように整形してくれるツールを導入した上で、開発されている人がほとんどかと思います。
PHPの場合は、代表的なチェックツールが php_codesniffer、整形ツールが php-cs-fixer となります。
(例えば JavaScript の場合、チェックツールが ESLint、整形ツールが Prettier といったように各言語でそのようなツールは存在しています)
一方、PHP のコーディング規約のこと以外にも、アプリケーションを実行せずに静的にコード品質をチェックする静的解析ツールなどが存在しています。
文法やコーディングスタイルについては、php_codesniffer で対応できるのですが、あくまで文法レベルでのチェックにすぎず、いくら文法が正しくともエラーは発生します。
では、なぜ PHP のエラーは実行時まで分からないのかと言いますと、PHP はスクリプト言語であるからです。
本来、C や Java といったコンパイル言語では、コンパイル時にエラーとなって気づくのですが、スクリプト言語である PHP は実行させるまで気づかないのです...
そこで未定義の変数があるかどうか、メソッドの引数や戻り値の型は問題ないか等、バグとなり得る原因の箇所を実行前に発見できるようにするのが、静的解析です。
今回はその PHP の静的解析ツールを Laravel に導入する方法について紹介します。
コーディング規約とは?
念の為、コーディング規約についてもご説明いたします。
そもそもコーディング規約とは、コードを書くためにルールを定めたものになります。
この規約をメンバーと共有しプロジェクトを進める事で、コードの共通化や、ソースコードリーディングの時間短縮が望めます。
例えば、PHPの言語ですと、コーディング規約として PSR (PHP Standards Recommendations) というものがあります。
PSR (PHP Standards Recommendations) は、PHP-FIG (PHP Framework Interop Group) が策定している PHP コーディング規約で、PSR1~19 の規約が存在しています。
その中でも、Laravelでは、ドキュメントに記載ある通りPSR-2とPSR-4の規約に準拠しているとのことですので、最低でもこの二つは守る必要があります。
https://readouble.com/laravel/9.x/ja/contributions.html#coding-style
しかし、PSR-2というのは、PHP-FIG によると、2019年の時点でPSR-2は既に非推奨となっており、代わりにPSR-12が推奨されているとのことです。
Deprecated - As of 2019-08-10 PSR-2 has been marked as deprecated. PSR-12 is now recommended as an alternative.
そのため、Laravel では
- PSR-4
- PSR-12
を守るようにコーディングしていくことになります。
※全てのコーディング規約については、下記リポジトリにまとめられていますので、興味ある方は覗いてみてください。
https://github.com/php-fig/fig-standards/tree/master/accepted
静的解析ツールについて
ここからがようやく本題の静的解析ツールについての説明です。
静的解析ツールを導入することで、下記のような問題を検知することが可能です。
- 存在しないクラスをインスタンス化している
- 存在しないメソッド、関数を呼び出している
- 参照しているクラス名の大文字小文字が定義と異なる
- メソッド仮引数とメソッド呼び出し実引数の型が一致しない
- メソッドに型宣言が指定されていない
- nullの可能性があるのに、メソッドを読んでいる
PHP の静的解析ツールとしては、下記のように色々と種類があるのですが、今回は PHPStan を利用します。
- PHPStan
- Psalm
- Phan
- PHPMD
今回はPHPで利用するのではなく、フレームワークの Laravel で利用します。
すると、Laravelの静的解析ツールとして Larastan というものが存在し Larastan 自体は、PHPStan の拡張の一つです。
Larastanには、Laravel アプリケーションで型情報などを PHPStan に認識させるための設定が含まれています。
上記の理由を踏まえ、Larastan を使うことにしましたので、利用する静的解析ツールをPHPStanに選定しました。
PHPStanとは
PHPStan は、Ondřej Mirtes(@OndrejMirtes)さんが開発している PHP コードの静的解析ツールで、MIT ライセンスで公開されています。
PHP で実装されており、Composer でインストールして利用できます。
https://phpstan.org/user-guide/getting-started
Laravelプロジェクトへの適用
それでは、ここからは実際の Laravel プロジェクトに対して、Larasan(PHPStan)を導入していきます。
インストール
Larastan は、Composer でインストール可能です。
1$ composer require --dev nunomaduro/larastan
インストールできているかも確認してみましょう。
1$ ./vendor/bin/phpstan -V
2PHPStan - PHP Static Analysis Tool 0.12.96
設定ファイルの作成
解析実行の設定ファイルを作成します。
設定ファイルは NEON という YAML に似たファイル形式で、 phpstan.neon
というファイル名で作成します。
1includes:
2 - ./vendor/nunomaduro/larastan/extension.neon
3parameters:
4 paths:
5 - app
6 - bootstrap
7 - config
8 - database
9 - resources/views
10 - routes
11 excludePaths:
12 - ./routes/console.php
13 level: 2
一つずつ解説していきます。
include ブロックでは、設定ファイルの読み込み等を指定しています。
Larastan を利用する際は、venderディレクトリの中nunomaduro/larastan/extension.neon を読み込みます。
parameters ブロックの pathでは、解析を実行するディレクトリを指定します。
反対に excludePaths を利用することで除外することも可能です。
levelの指定もあります。
level については、0から段階が設定されており、値が小さいほど緩く、値が高いほど厳しいチェックとなります。
いきなり導入した段階は多くのエラーが出ることが想定されるため、初めは0からスタートするのが良いでしょう。
解析実行
解析を実行するには、※phpstan コマンドを利用します。
下記コマンドで、先ほど作成した、phpstan.neon ファイルに基づいて解析が実行されます。
※実行時にメモリ不足によってエラーが起きる場合は、--memory-limit オプションをつけることでメモリ制限をコントロールできるので、1G等に設定し実行するとエラーは起きなくなるはずです。
1./vendor/bin/phpstan analyse --memory-limit=1G
エラーが検出されない場合
1[OK] No errors
エラーが検出される場合
1 ------ --------------------------------------------------------------------
2 Line index.php
3 ------ --------------------------------------------------------------------
4 13 Function something not found.
5 💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
6 ------ --------------------------------------------------------------------
7
8 [ERROR] Found 1 error
baselineファイルの作成
現段階でのエラー改善が難しい場合、baselineファイルを作成することで、そのエラーを無視するようにすることができます。
baseline ファイルは下記コマンドで作成可能です。
1./vendor/bin/phpstan analyse --generate-baseline
実行後、phpstan-baseline.neon というファイルが生成します。
生成したファイルをphpstan.neon で読み込むように指定することで、エラーが無視できるようになります。
1includes:
2 - ./vendor/nunomaduro/larastan/extension.neon
3 - phpstan-baseline.neon
4parameters:
5 paths:
6 - app
7 - bootstrap
8 - config
9 - database
10 - resources/views
11 - routes
12 excludePaths:
13 - ./routes/console.php
14 level: 2
静的解析の自動化
ここまでやれば、静的解析を実行できる環境が整いましたが、人によってはチェック有無で漏れが発生する可能性があります。
必ず実行されるように Github Actions に組み込んでいこうと思います。
1name: larastan
2
3on:
4 pull_request:
5 paths:
6 - "**.php"
7
8jobs:
9 larastan:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v2
13 - name: Setup PHP
14 uses: shivammathur/setup-php@v2
15 with:
16 php-version: '8.0'
17 tools: composer:v2
18 - name: Resolve dependencies
19 run: composer install --no-progress --prefer-dist --optimize-autoloader
20 - name: Run larastan
21 run: ./vendor/bin/phpstan analyse --memory-limit=2G --configuration=phpstan.neon
もし、解析実行時にエラーが起きた場合、PR作成後の commit ファイル上にエラー箇所を吐き出してくれるようになります。
(下記例では return での PHPDoc に記載されている型と実際に返ってくる型違いエラーの内容です)
今の PHPDoc の書き方ですと、型 App\Http\Controllers\Illuminate\Pagination\AbstractPaginator で認識してしまっているので、正しく型を認識できるようにしてあげる必要があります。
1# 現在
2* @return Illuminate\Pagination\AbstractPaginator
3
4# 修正後
5* @return \Illuminate\Pagination\AbstractPaginator
細かいのですが、どういった型を返すべきなのかについても注意するようになります。
まとめ
PHPStan などの静的解析ツールを導入することで、思わぬバグを防ぐこともできるようになります。
解析ツールによってバグが減り、トータルの開発工数も改善するはずですので、もし興味ある方は今からでも導入されてみてはいかがでしょうか?
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪、名古屋の4拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit