VSCode で PHP 開発するならインテリセンス最強の intelephense を使おう


こんにちは。
開発チームのワイルド担当、まんだいです。

今年はずっと PHP 開発をしていて、環境面については色々試行錯誤した一年だったと思います。
その甲斐もあってかなり便利に整備できてきたので棚卸しの意味も込めて記事にまとめたいと思います。

Visual Studio Code で行う PHP 開発

Visual Studio Code(以下、 VSCode )で開発するにあたって、初期のころは若干の不安もありました。

実は開発に入る前に PhpStorm の導入を検討していたのですが、諦めたという経緯があります。

PHP 開発のために開発されている IDE ですから、機能面では申し分ないと感じましたが、どうしても GUI が好きになれず。
こんなしょうもない理由ですが、1年以上付き合うわけですから、見てくれは重要なポイントだと思っています。

そんなわけで VSCode で開発をする、と決めたわけですが、拡張機能のない、おしゃれなメモ帳状態の VSCode では大規模開発はできません。

ネイティブの PHP サポートもありますが、ないよりマシ程度のものなので、 PhpStorm に迫る強力な拡張機能はないかと検証を進めていて見つけたのが intelephense です。

細かい中身のことは、 Langserver.org あたりを読んでいただくといいんじゃないかなと思いますが、何が気に入ったかというとインテリセンスの効きの良さ。

コード補完、コードジャンプがキビキビ動くのは感動的です。

さらに今回の開発では、 PHPDoc やタイプヒンティングをしっかり書いて進めていたのも功を奏して、引数の型違いなども即警告が出るのがナイスです。

それでもうまくコードジャンプできないことなどがあって、色々調べながらやっていたのですが、情報が少なくなかなか解決できなかったこともあり、少しばかり貯めこんだナレッジをご紹介していこうと思います。

 

設定をしっかりする

GitHub - bmewburn/vscode-intelephense: PHP intellisense for Visual Studio Codeにある通り、 VSCode 標準の PHP サポートを無効にします。

コード補完が重複して表示されたり、いいことは1つもないです。

ちなみに同じ PHP のインテリセンスである PHP IntelliSense も有効になっていれば、3つもヒントが出てくるので煩わしさが各段に上がります。

 

タイプヒンティングは書けるだけ書く

タイプヒンティングは書けば書くほど、 intelephense のチェックが機能するようになるのでどんどん書いていきたいところです。
PHP7からは、戻り値のタイプヒンティングを書けるようになったため、こちらも合わせて書いていきましょう。

/**
 * タイプヒンティングなしの場合
 */
function square($number)
{
    if (is_array($number)) {
        $sum = 0;
        foreach ($number as $n) {
            $sum+= $n;
        }
        return $sum;
    }
    return null;
}

 

上のコードはタイプヒンティングなしの状態ですが、処理を理解しないと引数にどんな値をセットするべきか判断できません。
これにタイプヒンティングを付けてみると以下のようになります。

/**
 * タイプヒンティングありの場合
 */
function square(array $number): ?float
{
    if (is_array($number)) {
        $sum = 0;
        foreach ($number as $n) {
            $sum+= $n;
        }
        return $sum;
    }
    return null;
}

 

かなり極端な例ですが、タイプヒンティングがあれば、中身を読まずとも引数の型も分かりどんな値が返ってくるのか一目瞭然ですね。

intelephense はメソッドの宣言部分とメソッドの直前に書かれた PHPDoc も合わせて表示してくれるため、いちいち確認する必要がなく便利です。

 

クラスプロパティをちゃんと型指定する

以下は AwesomeService クラスのユニットテストの冒頭部分です。

class AwesomeServiceTest
{
    protected $awesomeService;

    public function setUp()
    {
        $this->awesomeService = $this->app->make(AwesomeService::class);
    }

    // 以下省略
}

 

AwesomeService クラスをテスト毎に新しいものを作り直して、他のテストの影響を受けないようにするわけですが、この場合 $this->awesomeService->awesomeMethod() という感じでメソッドをたくさん書くことになるため、ここでこそコード補完の出番なわけですが、上のコードの状態では残念ながら補完が効きません。

この場合、クラスプロパティに型指定をしてあげることで補完が効くようになります。
補完が効くようにコメントを追加したのが以下のもの。

class AwesomeServiceTest
{
    /** @var AwesomeService */
    protected $awesomeService;

    public function setUp()
    {
        $this->awesomeService = $this->app->make(AwesomeService::class);
    }

    // 以下省略
}

 

PhpStorm などでも同様の仕組みで補完が効くようなので環境に依存せずみんながハッピーになるナイスなコメントですね。

 

ローカル変数もちゃんと型指定する

核心の一歩手前まで近づいていたのに辿り着けなかったのがローカル変数に対して型指定をする、といった内容ですが、これもコードを見てもらったほうが早いと思いますのでサンプルをどうぞ。

function superMethod()
{
    $awesomeService = $this->app->make(AwesomeService::class);
    $awesomeService->awesomeMethod();
}

 

この場合、 intelephense は $awesomeService の型が分からないので awesomeMethod() を補完することができません。
そこで、ローカル変数にも @var を使って型を教えてあげることで補完が効くようにします。

function superMethod()
{
    /** @var AwesomeService $awesomeService */
    $awesomeService = $this->app->make(AwesomeService::class);
    $awesomeService->awesomeMethod();
}

 

基本的な考え方はクラスプロパティと同じですが、クラス名の後に変数名を入れてあげるのがポイントのようです。
よくよく考えると、 @param と書き方は同じなのですが、クラス定義の前とクラス内で書く場所が違うため、ここに至るまで少し時間が掛かってしまいました。
開発規模が大きくなるとメソッド名も長くなりがち(個人的な見解です)なので、この一手間は惜しまないようにしていきたいですね。

 

まとめ

今回は VSCode で PHP 開発をする際に強力なツール、 intelephense の使い方でした。

個人的に気に入っている拡張機能ではありますが PHP 開発用の拡張機能の情報となると情報収集の難易度がグッと上がってしまうので、少しでも導入障壁を下げられればなと思い、便利な使い方の情報をまとめてみました。

色々開発が楽になるヒントを書いてみましたが、結局コード内のドキュメントを書く癖を日頃から付けよう、みたいなことですね。

また便利な機能を見つけたら追記していきたいと思います。

以上です。


この記事をかいた人

About the author

萬代陽一

ソーシャルゲームのウェブ API などの開発がメイン業務ですが、ありがたいことにマーケティングなどいろんな仕事をさせてもらえています。
なおビヨンド内での私の肖像権は CC0 扱いになっています。