PHPStanを導入した

Posted date at 2023-09-17

php

この記事について

PHPStanを導入したときのメモを一部修正して共有する。

PHPStanとは

PHPの静的解析ツール。 0~9段階の強度でPHPコードを解析し、エラーの発見や潜在的なエラー(Warning、非推奨)、型付けの強制などを機械的に行うことが可能。 PHPStan自体が依存パッケージの名前空間を分離していてパッケージ依存がないためアップデートの障壁になる可能性が低い。 また、Dockerを利用した開発環境では開発用のコンテナの中でインストールし動かせばいいため捨てるのも簡単で開発効率の向上のために入れておくと便利です。

PHPStanのインストール(Dockerで作成した開発環境の例)

PHPを実行するコンテナへ入り、Composerを利用してインストールします。($の後のコマンドが通常のターミナル、コンテナ内で実行するコマンドは#の後に記述します)

$ docker exec -it [PHPが実行できるコンテナ名] bash # cd /var/www/html/ # composer require --dev -W phpstan/phpstan phpstan/extension-installer

*/var/www/htmlがドキュメントルートでこのディレクトリ内にLaravelソースコードが展開されている構成です。

PHPStanの実行

$ docker exec laravel-web_sub /var/www/html/vendor/bin/phpstan analyze /var/www/html/app --memory-limit=256M

/var/www/html/appでLaravelのapp以下のディレクトリの解析を指定します。 CLIオプションで--memory-limit=256Mを指定しています。これはデフォルトだとメモリ不足でエラーが発生するためです。

レベルを指定して実行する例

最低レベル(レベル0)

$ docker exec laravel-web_sub /var/www/html/vendor/bin/phpstan analyze --level 0 ./var/www/html/app --memory-limit=256M

レベルMax(レベル8)

$ docker exec laravel-web_sub /var/www/html/vendor/bin/phpstan analyze --level max ./var/www/html/app --memory-limit=256M

実行結果例(清算Web)

$ docker exec laravel-web_sub /var/www/html/vendor/bin/phpstan analyze /var/www/html/app --memory-limit=256M 77/77 [aaaaaaaaaaaaaaaaaaaaaaaaaaaa] 100% ------ --------------------------------------------------------------------- Line Exceptions/Handler.php ------ --------------------------------------------------------------------- 53 Function respomse not found. ? Learn more at <https://phpstan.org/user-guide/discovering-symbols> ------ --------------------------------------------------------------------- ------ --------------------------------------------------------------------- Line Http/Kernel.php ------ --------------------------------------------------------------------- 62 Class App\\Http\\Middleware\\RedirectIfAuthenticated not found. ? Learn more at <https://phpstan.org/user-guide/discovering-symbols> ------ --------------------------------------------------------------------- ------ ---------------------------------------------------------------- Line Http/Middleware/RedirectIfAuthenticated.php ------ ---------------------------------------------------------------- 24 Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING on line 24 24 Syntax error, unexpected T_STRING, expecting ')' on line 24 27 Syntax error, unexpected T_ENCAPSED_AND_WHITESPACE on line 27 ------ ---------------------------------------------------------------- ------ ------------------------------------------------------------------- Line Library/ItemLib.php ------ ------------------------------------------------------------------- 81 Array has 2 duplicate keys with value 'k_ur_tanka' ('k_ur_tanka', 'k_ur_tanka'). 82 Array has 3 duplicate keys with value 'n_ur_soryo' ('n_ur_soryo', 'n_ur_soryo', 'n_ur_soryo'). ------ ------------------------------------------------------------------- ------ --------------------------------------------------------------------- Line Providers/AppServiceProvider.php ------ --------------------------------------------------------------------- 26 Call to static method startsWith() on an unknown class Str. ? Learn more at <https://phpstan.org/user-guide/discovering-symbols> ------ --------------------------------------------------------------------- [ERROR] Found 8 errors

レベル0で基本的なチェックを行ったところ8件のエラーが検出できました。

levelルールについてのメモ


  1. 基本的なチェック、未知のクラス、未知の関数、$thisで呼び出された未知のメソッド、それらのメソッドや関数に渡される引数の数が間違っている、常に未定義の変数
  2. 未定義の変数、__call__getを利用する未知のマジックメソッドやクラスプロパティの可能性
  3. 未知のメソッドが すべての式でチェックされ、PHPDocs が検証されます
  4. 戻り値の型、プロパティに割り当てられた型
  5. 基本的なデッドコードチェック。常に falseの値。instanceofおよびその他の型チェック、デッドelseブランチ、リターン後の到達不能コード。等
  6. メソッドと関数に渡される引数の型をチェックする
  7. 不足しているタイプヒントを報告する
  8. 部分的に間違った共用体型を報告する
    • 共用体型の一部の型にのみ存在するメソッドを呼び出すその他の間違っている可能性がある状況
  9. null 許容型のメソッドの呼び出しとプロパティへのアクセスをレポートする
  10. 型については厳密にする。mixed型に対して実行できる唯一の許可された操作は、型を別の型に渡すこと *Google翻訳

最後に

PHPStanをGithub ActionsやGitlab CIなどでプルリクエスト/マージリクエストの作成時に自動実行させ、特定のレベルのエラーを含むソースコードのマージをリジェクトする方法も他企業で採用されている例があります。 コードレビューや動作確認の手戻りを防ぐためにこちらも検討したい内容だと思います。

開発時に実行しないと発見できないエラーも探すことができ、コードの品質を高めるうえで非常に有用だと感じています。

最近の開発ではAPIによるデータ連携を実装しましたが、API側の実装にFatalエラーがあったことでレスポンスが返ってこなくなり原因の究明に時間がかかって開発体験が感じました。原因はPHPStanのレベル0で検出できるものであの時導入していれば…と思いました。

また、今後も使ってよかったことがあればこのブログで共有できればいいと思います。

←ホームに戻る