PHPの静的解析の方法やおすすめツールについて

採用はこちら

PHPの静的解析とは、プログラムを実際に実行せずにソースコードを解析し、型の不整合や未定義変数、存在しないメソッドの呼び出しなどの問題を検出する方法です。

PHPは動的型付け言語ですが、現在のPHPには引数型や戻り値型、プロパティ型、Union Typesなど、さまざまな型宣言機能が用意されています。

さらにPHPStanやPsalmなどの静的解析ツールを組み合わせることで、実際にプログラムを動かす前に多くの問題を発見できます。

例えば、次のコードを見てみましょう。

function getUserName(int $id): string
{
    return null;
}

戻り値にはstringが指定されていますが、実際にはnullを返しています。

このような型の矛盾は、PHPStanやPsalmなどを利用することで実行前に検出できます。

静的解析は、特に中規模以上のPHPプロジェクトや、Laravel・Symfonyなどを利用したWebアプリケーション開発において、コード品質を維持するための有効な手段です。

目次

PHPで静的解析を行うメリット

バグを実行前に発見できる

静的解析を導入する大きなメリットは、プログラムを実際に動かさなくても問題を発見できることです。

代表的には、次のような問題を検出できます。

  • 未定義変数
  • 引数の型の不一致
  • 戻り値の型の不一致
  • 存在しないメソッドの呼び出し
  • 存在しないプロパティへのアクセス
  • nullになる可能性がある値への不適切なアクセス
  • 到達不能なコード
  • 常にtrueまたはfalseになる条件
  • 不適切な配列操作

ただし、PHPではマジックメソッドやリフレクション、動的な処理なども記述できるため、すべての問題を必ず検出できるわけではありません。

静的解析ツールの設定や、利用しているフレームワークによって解析精度も変わります。

型安全性を高められる

PHPでは、関数の引数や戻り値に型を指定できます。

function add(int $a, int $b): int
{
    return $a + $b;
}

型宣言を利用することで、コードの意図を明確にできます。

さらに静的解析ツールを利用すると、より複雑な型の流れについてもチェックできます。

例えば、次のようなコードがあるとします。

$user = findUser();

echo $user->name;

findUser()の戻り値がUser|nullである場合、$usernullになる可能性があります。

静的解析ツールを利用すれば、このような潜在的な問題を検出できます。

リファクタリングしやすくなる

静的解析は、リファクタリング時にも役立ちます。

例えば、次のメソッドを、

$user->getName();

次のように変更したとします。

$user->name();

プロジェクト内に古いgetName()の呼び出しが残っていれば、静的解析によって検出できる場合があります。

クラス名やメソッド名、戻り値の型などを変更すると影響範囲が広くなることがありますが、静的解析を導入していれば変更によって発生した問題を発見しやすくなります。

コードレビューの負担を減らせる

単純な型ミスや未定義メソッドなどを人間が毎回コードレビューで確認するのは効率的ではありません。

静的解析ツールに機械的なチェックを任せることで、レビュー担当者は、

  • 設計が適切か
  • ビジネスロジックが正しいか
  • セキュリティ上の問題がないか
  • 可読性や保守性が高いか

といった、人間が確認すべき内容に集中しやすくなります。

PHPの静的解析でおすすめのツール

PHPのコード品質を確認するための代表的なツールには、次のものがあります。

ツール主な用途特徴
PHPStan静的解析型やコード構造に関する問題を幅広く検出
Psalm静的解析高度な型解析やPHPDocによる型表現に対応
PHP_CodeSnifferコーディング規約チェックPSR-12などのコーディング規約への違反を検出
PHP CS Fixerコード整形コーディング規約に合わせてコードを自動修正

PHPStanとPsalmは、本格的な静的解析ツールです。

一方、PHP_CodeSnifferとPHP CS Fixerは、主にコーディングスタイルや規約を確認するためのツールです。

目的が異なるため、実務では複数のツールを組み合わせて使用するケースもあります。

PHPStanで静的解析する方法

PHPStanとは

PHPStanは、PHPで広く利用されている静的解析ツールの一つです。

PHPコードを実行することなく解析し、型の不整合や不正なメソッド呼び出しなどの問題を検出します。

ローカル環境だけでなく、GitHub ActionsなどのCI環境で実行することも可能です。

初めてPHPの静的解析を導入する場合、PHPStanは有力な選択肢の一つです。

PHPStanをインストールする

PHPStanはComposerを使ってインストールできます。

composer require --dev phpstan/phpstan

--devを指定することで、開発用の依存パッケージとして追加されます。

PHPStanを実行する

例えば、srcディレクトリを解析する場合は次のように実行します。

vendor/bin/phpstan analyse src

srctestsを両方解析したい場合は、次のように指定できます。

vendor/bin/phpstan analyse src tests

PHPStanの設定ファイルを作成する

PHPStanでは、プロジェクトルートにphpstan.neonなどの設定ファイルを作成できます。

例えば、次のように設定します。

parameters:
    level: 6

    paths:
        - src
        - tests

設定ファイルを作成しておけば、次のコマンドだけで指定したディレクトリを解析できます。

vendor/bin/phpstan analyse

PHPStanの解析レベルを設定する

PHPStanには、解析の厳しさを調整するレベルが用意されています。

現在はレベル0からレベル10までの11段階があり、数字が大きくなるほど厳しい解析が行われます。

例えば、コマンドでレベル6を指定する場合は次のようにします。

vendor/bin/phpstan analyse -l 6 src

既存の大規模プロジェクトで、いきなり高いレベルを指定すると大量のエラーが発生する可能性があります。

そのため、既存プロジェクトでは、

低いレベルから解析
↓
エラーを修正
↓
解析レベルを上げる
↓
さらにエラーを修正

という形で段階的に導入する方法があります。

新規プロジェクトであれば、開発初期から比較的厳しい設定を採用する方法も有効です。

PHPStanのBaselineを活用する

Baselineとは

既存の大規模プロジェクトにPHPStanを導入すると、数百件や数千件のエラーが表示される場合があります。

このような場合に利用できるのがBaselineです。

Baselineを使用すると、現在存在する既知のエラーを記録し、それ以外の新しいエラーに集中しやすくなります。

Baselineは次のように生成できます。

vendor/bin/phpstan analyse --generate-baseline

既存コードをすぐにすべて修正することが難しい場合に便利な機能です。

ただし、Baselineに大量の問題を登録して放置するのではなく、既存のエラーも少しずつ減らしていくことが重要です。

Psalmで静的解析する方法

Psalmとは

Psalmも、PHPを代表する静的解析ツールの一つです。

型の推論やPHPDocを利用した詳細な型表現などに対応しており、大規模なPHPプロジェクトでも利用できます。

PHPStanとPsalmはいずれも高度な型解析に対応しているため、プロジェクトとの相性や既存の開発環境、チームの経験などを基準に選択するとよいでしょう。

Psalmをインストールする

PsalmはComposerからインストールできます。

composer require --dev vimeo/psalm

インストール後は、次のコマンドで設定を初期化できます。

vendor/bin/psalm --init

その後、次のコマンドを実行すると静的解析できます。

vendor/bin/psalm

なお、最新バージョンのPsalmにはPHPのバージョン要件があります。

古いPHP環境で利用する場合は、使用するPsalmのバージョンと対応PHPバージョンを事前に確認することが重要です。

PHPStanとPsalmはどちらがおすすめ?

初めて導入するならPHPStanは有力な選択肢

PHPStanは、Composerで簡単に導入でき、解析レベルを段階的に設定できます。

また、さまざまなフレームワークやライブラリ向けの拡張が存在するため、一般的なPHPのWebアプリケーションにも導入しやすいツールです。

例えば、次のような場合に適しています。

  • PHPの静的解析を初めて導入する
  • 段階的に解析を厳しくしたい
  • CI/CDへ組み込みたい
  • LaravelやSymfonyなどのプロジェクトで利用したい
  • 既存プロジェクトに静的解析を追加したい

Psalmも高度な型解析に対応している

Psalmも、高度な型解析を行える静的解析ツールです。

PHPDocによる型表現や型推論などを活用できるため、型情報を細かく管理したいプロジェクトでも利用できます。

ただし、PHPStanにも高度な型解析やジェネリクス、詳細なPHPDoc型などの機能があります。

そのため、「PHPStanは簡易的、Psalmは高度」と単純に分けるのではなく、プロジェクトとの相性を見ながら選択するのが適切です。

LaravelでPHPStanを使う場合はLarastanも検討する

Larastanとは

Laravelでは、FacadesやEloquentなど、フレームワーク独自の仕組みが多く使用されています。

そのため、PHPStan本体だけではLaravel固有のコードを十分に解析できない場合があります。

Laravelプロジェクトでは、PHPStan向けの拡張であるLarastanを組み合わせる方法があります。

Larastanを利用すると、Laravelの仕組みを考慮した静的解析を行いやすくなります。

LaravelでPHPStanを導入する場合は、PHPStan本体だけでなくLarastanの利用も検討するとよいでしょう。

PHP_CodeSnifferでコーディング規約をチェックする

PHP_CodeSnifferとは

PHP_CodeSnifferは、PHPコードが指定したコーディング規約に従っているかをチェックするツールです。

PHPStanやPsalmとは目的が異なり、主にコードスタイルを確認するために利用します。

例えば、

if($user){
echo $user->name;
}

のようなコードについて、スペースやインデント、改行などが設定した規約に従っているかをチェックできます。

PHPStanとの違いを簡単に表すと、

PHPStan
→ 型やコード構造の問題を静的に解析

PHP_CodeSniffer
→ コーディング規約への違反をチェック

となります。

PSR-12などのルールを利用できる

PHP_CodeSnifferでは、PHPの代表的なコーディング規約であるPSR-12などを利用できます。

チーム開発でコードの書き方を統一したい場合に便利です。

なお、PHP_CodeSnifferの公式プロジェクトは現在PHPCSStandards/PHP_CodeSnifferで管理されています。

古い記事では以前のリポジトリを案内している場合があるため、情報を確認する際には注意しましょう。

PHP CS Fixerでコードを自動修正する

PHP CS Fixerとは

PHP CS Fixerは、設定したコーディングルールに合わせてPHPコードを自動修正するツールです。

PHP_CodeSnifferが主に規約違反の検出を行うのに対して、PHP CS Fixerはコードを自動的に整形できます。

例えば、

if($user){
    echo $user->name;
}

といったコードを、設定したルールに従って整形できます。

PHP CS FixerではPSR-12などのルールセットも利用できます。

PHPの静的解析ツールを組み合わせる方法

PHPStan・PHP CS Fixer・PHPUnitを組み合わせる

実務では、静的解析ツールだけですべての品質管理を行うのではなく、目的の異なるツールを組み合わせる方法が効果的です。

例えば、

PHPStan
+
PHP CS Fixer
+
PHPUnit

という構成があります。

それぞれの役割は次のとおりです。

PHPStan
→ 型やコード構造に関する問題を静的に検出

PHP CS Fixer
→ コーディングスタイルを自動修正

PHPUnit
→ コードを実際に実行して期待する動作をテスト

静的解析とテストは、どちらか一方だけ行えばよいものではありません。

静的解析ではコードの構造や型に関する問題を発見し、テストでは実際の処理結果が仕様どおりかを確認します。

PHPの静的解析をCI/CDに組み込む

Pull Requestごとに自動実行する

静的解析は開発者のPCだけで実行するのではなく、GitHub ActionsなどのCIへ組み込むと効果的です。

例えば、Pull Requestを作成した際に次の処理を自動実行します。

composer install

vendor/bin/phpstan analyse

PHPStanがエラーを検出した場合にCIを失敗させるよう設定すれば、問題のあるコードがマージされるのを防ぎやすくなります。

開発フローとしては、次のようになります。

コードを変更
↓
Pull Requestを作成
↓
静的解析
↓
自動テスト
↓
コードレビュー
↓
マージ

チーム開発では、開発者ごとの環境差を減らすためにもCIによる自動チェックが有効です。

既存PHPプロジェクトへ静的解析を導入するコツ

最初からすべてのエラーを直そうとしない

長期間運用されているPHPプロジェクトでは、初めて静的解析を実行すると大量のエラーが表示される場合があります。

この場合は、一度にすべてを修正しようとせず、段階的に進める方法が現実的です。

例えば、

解析対象を限定する
↓
低い解析レベルから始める
↓
重要なエラーから修正する
↓
解析範囲を広げる
↓
解析レベルを上げる

という流れです。

必要に応じてPHPStanのBaselineも利用できます。

型宣言を積極的に利用する

静的解析の精度を高めるには、PHPの型宣言を積極的に使用することが重要です。

function findUser(int $id): ?User
{
    // ...
}

このように、

  • 引数型
  • 戻り値型
  • プロパティ型

などを明確にすると、静的解析ツールがコードを理解しやすくなります。

PHPDocを活用する

PHPのネイティブ型だけでは表現しにくい型については、PHPDocを利用できます。

例えば、

/** @var array<int, User> $users */
$users = [];

と記述することで、単なるarrayではなく「整数をキーとしてUserオブジェクトを格納する配列」という情報を静的解析ツールへ伝えられます。

静的解析ツールでは、

array<string, User>
list<User>
User|null

などの詳細な型情報も活用できます。

PHPの静的解析だけですべてのバグを発見できるわけではない

ビジネスロジックの間違いまでは判断できない

静的解析は便利ですが、すべての不具合を発見できるわけではありません。

例えば、次のコードを考えてみましょう。

function calculatePrice(int $price): int
{
    return $price * 2;
}

型としては問題ありません。

しかし、仕様上は「価格に10%を加算する」のが正しかった場合、このコードはビジネスロジックとして間違っています。

静的解析ツールは、基本的に仕様書まで理解して正しい計算式を判断するものではありません。

そのため、

静的解析
+
単体テスト
+
結合テスト
+
コードレビュー

を組み合わせることが重要です。

PHPの静的解析にはPHPStanやPsalmを活用しよう

PHPの静的解析を導入すると、型の不一致や未定義変数、不正なメソッド呼び出しなど、さまざまな問題を実行前に発見しやすくなります。

代表的な静的解析ツールにはPHPStanとPsalmがあります。

初めて導入する場合には、Composerで手軽に導入でき、解析レベルを段階的に変更できるPHPStanが有力な選択肢です。

一方、Psalmも高度な型解析に対応しているため、プロジェクトの環境やチームの運用方針に合わせて選択するとよいでしょう。

また、静的解析だけではコード品質を完全に保証することはできません。

実務では、

PHPStanまたはPsalm
→ 静的解析

PHP_CodeSniffer
→ コーディング規約チェック

PHP CS Fixer
→ コードスタイルの自動修正

PHPUnit
→ 動作テスト

のように、目的の異なるツールを組み合わせる方法が効果的です。

さらにGitHub ActionsなどのCI/CDへ静的解析を組み込めば、問題のあるコードが本番環境へ入るリスクを減らせます。

PHPは動的型付け言語ですが、現在ではPHP本体の型宣言機能に加えてPHPStanやPsalm、PHPDocなどを活用することで、高いレベルでコードの問題を開発段階に検出できる環境を構築できます。

以上、PHPの静的解析の方法やおすすめツールについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次