【テクニカル・上級編】PhpStorm×PHPStan・Psalm連携:型推論の限界を超える最強の静的解析ワークフロー – 総合開発環境(IDE)生産性向上バイブル

PhpStorm×PHPStan・Psalm連携:型推論の限界を超える最強の静的解析ワークフロー

数多のIDEを渡り歩いてきたシニアアーキテクトなら同意するはずだ。PhpStorm標準のインスペクションは、日々の開発において驚異的な速度でコードの不整合を暴いてくれる。しかし、大規模なドメインモデル、複雑なジェネリクス(`@template`)、あるいはサードパーティライブラリの深い抽象化の迷宮に足を踏み入れた瞬間、IDE単体の型推論は限界を迎える。

「なぜこの配列の形状(Shape)を推論できないのか?」
「なぜこのNull合体演算子の先でオプショナルが外れないのか?」

CI(Continuous Integration)パイプラインを回し、数分後にGitHub ActionsやGitLab CIから「PHPStan Level 8 Error」という冷酷な通知を受け取る。この「フィードバックループの遅延」こそが、エンジニアの認知負荷を高め、フロー状態を破壊する最大のガンだ。

CIの結果を待つな。保存した瞬間、いや、タイプしているその瞬間に、プロジェクト全体の厳格な静的解析結果がエディタを支配していなければならない。

本稿では、PhpStorm、Dockerコンテナ、そしてPHPStan/Psalmを完全に融合させ、CI/CDパイプラインと完全に同期した「ローカル・リアルタイム型安全要塞」を構築する極意を授ける。

—

1. 内部アーキテクチャの理解:なぜIDEとCLI解析結果が乖離するのか?

まず、敵を知ることから始めよう。PhpStormの静的解析エンジンと、PHPStan/Psalmのアーキテクチャには決定的な違いがある。

  • PhpStormの解析: AST(抽象構文木)をベースに、メモリ上でインクリメンタルにコード片を評価する。速度は狂気的に速いが、プロジェクト全体を跨ぐ高度な条件分岐の追跡や、高度なPHPDocジェネリクスの合成において「楽観的(保守的)」に振る舞う傾向がある。
  • PHPStan / Psalmの解析: 独自のスコープ分析エンジンを持ち、指定されたルールレベル(Level 0〜9)に基づき、コードパスの網羅的な到達可能性(Reachability)と型の整合性を数学的に証明する。

これらをIDE上でシームレスに同居させるには、単にプラグインをインストールするだけでは不十分だ。「どのランタイム(PHP環境)で、どの設定ファイルを読み込み、どのようにプロセスを常駐させるか」というライフサイクルを設計する必要がある。

—

2. Docker環境におけるPHPStan/Psalmの完全統合

モダンな開発において、ローカルホストに直接PHPランタイムをインストールすることはもはやアンチパターンだ。Docker Compose環境で稼働するアプリケーションに対し、PhpStormがどのように外部ツールを実行すべきか。ここが最初の難所であり、最大のパフォーマンス最適化ポイントとなる。

外部ツールとしての登録

PhpStormの `Settings / Preferences` > `PHP` > `Quality Tools` から、PHPStan(またはPsalm)を設定する。ここでローカルのバイナリを指定してはならない。必ず「Remote Interpreter(Docker / Docker Compose)」をバインドする。

ここで発生しがちなのが「プロセス起動のオーバーヘッドによるエディタのフリーズ」だ。PhpStormがファイル保存のたびに `docker-compose run` を叩くと、コンテナの起動・破棄コストによりIDEが重くなる。

これを防ぐため、PHPStanはデーモンモード(もしくはワンショット実行の最適化)を意識したCLIラッパーを介して呼び出す。

プロジェクトルートに配置する、最適化された `phpstan.neon` のエンタープライズ構成例を見てほしい。

phpstan.neon
parameters:
# 解析の厳格度(最高峰の安全性を担保するLevel 8)
level: 8

# 解析対象ディレクトリの指定
paths:

  • src
  • tests

# PhpStormの型補完と完全に同期させるためのbootstrapファイル
bootstrapFiles:

  • .phpstan/bootstrap.php

# 除外すべき自動生成ファイルなど
excludePaths:

  • src/Migration/

# ジェネリクスの型チェックを厳格化
treatPhpDocTypesAsCertain: false

—

3. PhpStormインスペクションへの完全統合(Inspection設定の極意)

外部ツールを動かすだけなら誰でもできる。問題は、それを「PhpStormのエディタ上にどうマッピングするか」だ。

`Settings` > `Editor` > `Inspections` > `PHP` > `Quality Tools` から、`PHPStan validation` および `Psalm validation` を有効化する。

ここで設定すべきキモは以下の通り:

1. 「Run inspection for PHP_CodeSniffer / PHPStan / Psalm based on fixed scope」の最適化。プロジェクト全体を毎回スキャンさせるとメモリを食いつぶすため、「Scope: Current File(現在のファイル)」を基本とし、ファイルの保存時(On Save)または手動トリガー(Shortcut)に絞る。
2. エラーレベルのマッピング: PHPStanの「Error」をPhpStormの「Error(赤波線)」に、PHPStanの「Warning」をPhpStormの「Weak Warning(黄緑ハイライト)」に正確にマッピングする。これにより、IDEの「Problems」ツールウィンドウに、CIと全く同じコード品質メトリクスがリアルタイムで集約される。

—

4. CI/CDパイプラインとの完全同期:ローカルとリモートの乖離をゼロにする

「ローカルではエラーが出ないのに、GitHub ActionsのCIで落ちた」——この絶望的な体験を根絶する。原因の9割は、ローカルのPHPStan実行環境(PHPバージョン、PECL拡張機能、composer依存関係)と、CIサーバーの環境の不一致にある。

以下のGitHub Actionsワークフロー定義は、PhpStormから叩いているDockerコンテナの構成と完全に一致させた上で、型解析を並列処理・キャッシュする最高峰のパイプラインだ。

name: Static Analysis Fortress

on:
pull_request:
branches: [ main, develop ]
push:
branches: [ main, develop ]

jobs:
phpstan:
name: PHPStan Level 8 Analysis
runs-order: ubuntu-latest

# ローカルのDocker環境と同じ公式PHPイメージを使用
container:
image: php:8.3-cli-bookworm

steps:

  • name: Checkout Repository

uses: actions/checkout@v4

  • name: Setup PHP Extensions & Composer Cache

uses: shivammathur/setup-php@v2
with:
php-version: ‘8.3’
extensions: mbstring, xml, ctype, iconv, intl, pdo_mysql
tools: composer:v2
env:
update: true

  • name: Get Composer Cache Directory

id: composer-cache
run: echo “dir=$(composer config cache-files-dir)” >> $GITHUB_OUTPUT

  • name: Cache Composer Dependencies

uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${

タイトルとURLをコピーしました