プラグイン(拡張アプリ)の静的解析


プラグインのコードを PHPStan で静的解析し、実行前に型の不整合やタイプミスを見つけられるようにする手順です。テスト基盤 ablogcms/testing-framework に PHPStan 設定が同梱されており、設定 ファイル1 行の読み込みで a-blog cms 本体のシンボル(関数・クラス・定数)を解決した状態で解析できます。

PHPStan とはPHPプログラムの実行前にコードの品質をチェックする「静的解析ツール」です。

https://phpstan.org/

なぜ設定が必要なのか

プラグインは本体の関数(config() / dsn() など)やクラス(SQL など)、定数(BID など)を使います。PHPStan はコードを実行せずに解析するため、これらのシンボルが「どこで宣言されているか」を教えてあげないと「未定義」と誤検知します。

配布パッケージの一部(ACMS/function.php など)は難読化されていて静的には読めません。テスト基盤はその分を スタブ(シンボルの宣言だけを持つファイル)で補い、読めるコアは実ソースを直接読ませることで、どんな環境でも同じ設定で解析できるようにしています。開発者側は、同梱設定を includes で読み込むだけで済みます。

設定

phpstan/phpstanrequire-dev に追加し、プラグイン直下に phpstan.neon(または phpstan.neon.dist)を置きます。

{
  "require-dev": {
    "ablogcms/testing-framework": "3.2.*",
    "phpstan/phpstan": "^2.1"
  }
}
includes:
  - vendor/ablogcms/testing-framework/phpstan/extension.neon
parameters:
  level: max
  # 本体のサポート範囲(PHP 8.1〜8.5)で解析し、新旧バージョン差の取りこぼしを防ぐ
  phpVersion:
    min: 80100
    max: 80500
  paths:
    - src
    - tests          # テストも型チェックする(基盤の基底クラスは include で解決される)
  scanDirectories:
    - /var/www/html/php   # a-blog cms 本体の読めるコア(ACMS_ROOT 配下の php ディレクトリ)
  • includes … テスト基盤同梱の extension.neon を読み込みます。ここが本体シンボル解決の入口です。

  • scanDirectories … 難読化されていない本体コア(Services/SQL/ など)を実ソースから読ませます。パスは環境に合わせて読み替えてください(同梱イメージ appleple/acms なら /var/www/html/php)。

  • phpVersion … 本番のサポート範囲全体(8.1〜8.5)を対象にします。実行時の PHP に依存せず、バージョン差に由来する取りこぼしを防げます。

  • bootstrapFiles は不要です。 プラグイン実行時にのみ確定する定数(PLUGIN_DIR / PLUGIN_LIB_DIR など)は同梱 extension が供給します。

新規プラグインは最初から level: max で始めるのがおすすめです。あとから上げるより、積み上がる差分が小さくて済みます。

実行

本体を含む環境(Docker コンテナ)の中で実行します。

vendor/bin/phpstan analyse

誤検知が出たら

本体のレガシー領域に由来する誤検知が出ることがあります。基本方針は baseline(一括で握りつぶすファイル)を作らず、該当行に理由コメント付きで局所的に抑制することです。baseline は「いつの間にか本物のエラーまで隠れる」ため、増やしすぎないほうが安全です。

// @phpstan-ignore-next-line (理由: 本体レガシー API の戻り値型が緩いため)
$value = legacy_api();

識別子付きで抑制できる場合は、対象を絞って書くとより安全です。

$value = legacy_api(); // @phpstan-ignore return.type (理由: …)

あわせて行う品質チェック(phpcs)

PHPStan は「型・ロジックの誤り」を見ますが、コーディング規約(PSR-12)の統一は範囲外です。自分のプラグインでも squizlabs/php_codesnifferrequire-dev に入れて phpcs を回しておくと、テスト・静的解析・規約チェックの品質ゲートが揃います。phpcs も PHPStan と同じく実行時の PHP に依存しないので、CI では PHP マトリクスで回さず 1 回だけ実行すれば十分です(CI と複数バージョン検証)。

補足

  • 同梱スタブは、本体の公開 API・定数のスナップショットです。本体側で大きめの API 追加があった場合は、その追加を含むバージョンの ablogcms/testing-framework に更新すると、新しい API も解決できるようになります。

関連ドキュメント