0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPStanのStubファイル作ってみる

Last updated at Posted at 2024-12-28

初めに

PHPStanにはStubという機能があり、解析時、本来のファイルではなく別ファイルに定義したPHPDocを参照することができます。今回はこのStubについて解説します。

Stubとは

前述の通り、実際のコードの代わりにメソッドやクラスのインターフェースを定義できる機能です。
vendor配下にあるサードパーティ製のコードのPHPDocが誤っている場合PHPStanはうまく解析ができません。その場合でもstubファイルを用いれば正しく解析を行うことができます。

スタブファイルの拡張子は.stub.phpです。

Stubを作ってみよう

ということでStubファイルを作ってみましょう。
ディレクトリ構成は以下です。

※サードパーティのファイルは本来vendor配下にあると思うのですが、簡潔にしたいので一旦以下のようにしてます

Project
    ├ src
    |   ├ analyseObject
    |   |   └ StubTest.php ← 解析対象
    |   └ thirdparty
    |       └ ThirdParty.php ← サードパーティ製の間違ったPHPDocを持つファイル
    └ stub
        └ ThirdParty.stub ← 正しいPHPDocを記載したスタブファイル

課題:サードパーティ製のコードのPHPDocが間違っていて、解析結果が正しくない

まずはサードパーティ製のソースを以下のように作成しました。
PHPDocには@return intとありあたかもintを返すようですが、実際にはstringにcastをしており、PHPDocが間違っていることが分かると思います。

ThirdParty.php
<?php
namespace Path\to\project\thirdparty;

class ThirdParty
{
    /**
     * @param int $intArg
     * @return int
     */
    public function thirdPartyMethod($intArg)
    {
        return (string)$intArg; // stringを返すが、PHPDocではintが返るように記載されている!
    }
}

このサードパーティ製のメソッドを利用する箇所は以下です。
先ほど見せたサードパーティ製のメソッドを呼び出してそのまま返却しているため、returnするタイプをstringにしています。

StubTest.php
class StubTest
{
    public function call(): string
    {
        $thirdParty = new ThirdParty();
        return $thirdParty->thirdPartyMethod(10);
    }
}

この状態で解析をかけると、以下のようにreturのタイプが間違っているという旨のエラーが出てきます。しかし、実際に間違っているのはサードパーティ製のコードのPHPDocであり、このエラーは過検知であるといえます。

$ ./vendor/bin/phpstan analyse .\src\analyseObject\StubTest.php
Note: Using configuration file C:\Path\to\project\phpstan.neon.
 1/1 [============================] 100%

 ------ ---------------------------------------------------------------------------------------------- 
  Line   StubTest.php
 ------ ----------------------------------------------------------------------------------------------
  :11    Method Path\to\project\analyseObject\StubTest::call() should return string but returns int.
         ✏️  StubTest.php
 ------ ----------------------------------------------------------------------------------------------
                                                                                                                        
 [ERROR] Found 1 error                                                                         

解決策:Stubファイルを利用する

ここでstubファイルの出番です。
以下のように、サードパーティ製のファイルと同じ名前空間で同じクラス名、同じメソッド名で定義しています。違う箇所は、returnするタイプをstringに変更したのみです。

ThirdParty.stub
<?php
namespace Path\to\project\thirdparty;

class ThirdParty
{
    /**
     * @phpstan-param int $intArg
     * @phpstan-return string
     */
    public function thirdPartyMethod($intArg);
}

続いて、作成したスタブファイルをPHPStanに認識させましょう。
neonファイルに以下のように追加してください。

phpstan.neon
parameters:
    stubFiles:
        - stub/ThirdParty.stub

この状態でもう一度解析を実行すると、先ほどのエラーが消えてくれました。

$ ./vendor/bin/phpstan analyse .\src\analyseObject\StubTest.php
Note: Using configuration file C:\Path\to\project\phpstan.neon.
 1/1 [============================] 100%

 [OK] No errors                                                                                

終わりに

PHPStanのスタブファイルはサードパーティ製のコードを変更せずに正しい結果を返すことができる素晴らしい機能です。このような場合には是非使ってみてください。

ここまでご覧いただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?