CakePHPにIDE Helperを導入しIDE補完で開発効率を上げる⚡️【CI連携】

こんにちは、みやがわです。

CakePHPで開発を行う上で必ず導入したいライブラリの一つである IDE Helper をご紹介します。


## 環境

- CakePHP: 4.4.15 （ 3版もあります ）
- PHP: 8.1.20

<br>

## IDE Helperとは

IDE Helperとはその名の通りIDEやエディタを補助するためのプラグインで、主に補完の面でサポートします。

PHPの言語仕様に対応しているIDEでは最初からある程度の補完はされますが、扱うフレームワークがマジックメソッドを持っていたり特殊なインスタンス参照を行っている場合には適切な補完を表示することが出来ません。

CakePHPの場合、そういった補完を適切に表示するためにはクラスのPHPDocに対して `@property`タグを追加する必要があります。

例） `$this→loadComponent()` で読み込んだクラスの補完を効かせるために `@property` タグを追加している
![Screenshot 2023-08-11 at 16.26.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390133/61fb27af-4838-9c0c-dbf3-1ebf10563115.png)

ただし実際の開発で問題になるのは、このPHPDocの追加を忘れてしまったり、コードの実態とPHPDocが乖離する可能性があることです。そのためフレームワークに用意されたIDE Helperを適切に用いて、そういった問題を解決しながら、常に補完の効く開発環境を作りましょう。

### CakePHP IDE Helper

`dereuromark/cakephp-ide-helper`

https://github.com/dereuromark/cakephp-ide-helper/tree/master

CakePHPのコアメンバーによりメンテナンスされているライブラリです。メンテナンス頻度も高く信頼できます。

出来ることは主にこの3つです。

- アノテーション（PHPDoc）の追加と修正 および 不要なアノテーションの削除
- 上記の差分検知（CI統合用）
- PhpStorm用メタファイル生成

上記以外にもいくつかあるので[ドキュメントをご参照ください。](https://github.com/dereuromark/cakephp-ide-helper/tree/master/docs#overview)

<br>

## 導入方法

[ドキュメント](https://github.com/dereuromark/cakephp-ide-helper/tree/master/docs#install)

#### インストール

```bash
composer require --dev dereuromark/cakephp-ide-helper
```

#### 読み込み設定

```bash
bin/cake plugin load IdeHelper
```

これを実行することで `src/Application.php` に追記されます。

```diff:src/Application.php
    public function bootstrap(): void
    {
+       $this->addPlugin('IdeHelper')
    }
```

ただし、不要な読み込みを防いだりCIを考慮すると、下記のように bootstrapCli() 内でオプショナルに読み込むのがおすすめです。

```diff:src/Application.php
    protected function bootstrapCli(): void
    {
+       $this->addOptionalPlugin('IdeHelper');
    }
```

<br>

## アノテーション実行コマンド

[ドキュメント](https://github.com/dereuromark/cakephp-ide-helper/blob/master/docs/Annotations.md)に複数コマンドが書かれていますが、個人的に下記があれば十分だと思います。

```bash
# アノテーション追加
bin/cake annotate all -r

# アノテーション差分検知
bin/cake annotate all -r -d --ci
```

オプション説明

- `-r` : removeオプション。既存Docで不要な行を削除。
- `-d` : dry-runオプション。変更有りなしを検知。
- `--ci` : ciオプション。差分検出時のステータスコードが2になります。（※ 上手く行かないケースがあったので回避方法を後述します）

<br>

## アノテーション追加実行例

事前準備として下記を行い、アノテーション実行時にPHPDocが更新されるかを見てみます。

#### 事前準備

[該当コミット](https://github.com/NaoyaMiyagawa/cakephp4-ide-helper-demo/pull/5/commits/27ef844eb28ab16f5c8cb4c052d742d5f022845b)

- Viewファイルで新規変数を利用（Controllerからsetされた変数を利用するケース）
- Migrationファイル追加
- Componentファイル追加して、Controllerで読み込み
- Behaviorファイル追加して、Tableで読み込み
- Viewヘルパーファイルを追加して、AppViewで読み込み

#### 実行例

読み込みを追加したファイルに適切にアノテーションが追加されています。

[該当diffコミット](https://github.com/NaoyaMiyagawa/cakephp4-ide-helper-demo/pull/5/commits/272a59442220fa1a3477de0eaef63091879c4a4e)
![Screenshot 2023-08-12 at 23.47.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390133/289732e2-d75b-d3ec-9c82-ef35bfeb42f6.png)

<br>

## CI連携（GitHub Actions）

開発時に大事なのはこのアノテーション追加をもれなく実行することです。PRへpush時にCIで差分有無を検知できるようにしましょう。

#### composerコマンド追加

手動実行とCI実行で結果に差が起きないように、実行コマンドをcomposerコマンド化しておきましょう。

また、上述のCIオプションでは差分があってもエラーにならないケースが稀にありましたので、力技ですが下記のように出力結果を文字列検索する方式で代替します。

```json
    "scripts": {
        "annotate-check": "RESULT=$(bin/cake annotate all -r -d); echo \"$RESULT\"; NEEDS_FORMAT=$(echo \"$RESULT\"| grep -e 'added' -e 'updated' -e 'removed'); if [ ! \"$NEEDS_FORMAT\" ]; then echo \"\n\\e[30;42m[Success] IdeHelper: Nothing to annotate.\\e[m\n\"; exit 0; else echo \"\n\\e[41m[Error] IdeHelper: Detected code to annotate. Please run 'composer annotate-fix'.\\e[m\n\"; exit 2; fi;",
        "annotate-fix": "bin/cake annotate all -r",
    },
```

#### GitHub Actions設定

CakePHP IDE Helperでは実際のDBのテーブル構成とEntityのプロパティが合致するかを見るため、CI上でもDBコンテナを立ち上げて、事前にマイグレーションを実行する必要があります。

[該当コードはこちら](https://github.com/NaoyaMiyagawa/cakephp4-ide-helper-demo/tree/main/.github)

```yaml:.github/workflows/ci.yml
  php--ide-helper:
    name: Ide Helper
    runs-on: ubuntu-20.04
    services:
      postgres:
        image: postgres:14-alpine
        env:
          POSTGRES_DB: ide-helper-demo
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v3
      - uses: ./.github/actions/php/setup
      - uses: ./.github/actions/php/run-cakephp-ide-helper
```

```yaml:.github/actions/php/run-cakephp-ide-helper/action.yml
name: Run CakePHP IDE Helper

runs:
  using: composite

  steps:
    - name: Install IDE Helper
      run: composer require --dev cakephp/cakephp-codesniffer
      shell: bash

    - name: Create Database For ide-helper
      run: bin/cake migrations migrate
      shell: bash

    - name: Run ide-helper
      run: composer annotate-check
      shell: bash
```

### CI実行結果

**差分検知時**

これで安心ですね🌿
![Screenshot 2023-08-13 at 13.58.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390133/7ca6bb38-e87b-aadb-b23e-d31646d879d7.png)

<br>

## おわりに

補完が効くだけで開発効率は圧倒的に良くなります。またレビュー時においても、PHPDocの更新漏れが無いかと枝葉な点に時間を注がなくてもよくなります。

IDE HelperはCakePHPだけでなく、Laravelにも固有のライブラリがあるので、ぜひ導入してみてください。

本記事で取り上げたライブラリは、どのCakePHPプロジェクトでも導入すべきライブラリだと思いますので参考になれば幸いです。

<br><br>


## 補足

アノテーション追加コマンド以外にもPhpStorm用のmetaファイル生成機能があります。

```bash
bin/cake phpstorm generate
```

これを利用すると、下記の[ドキュメント](https://github.com/dereuromark/cakephp-ide-helper/blob/master/docs/Generator.md#tablefinders)の通り、finderまで補完が効くようになります！
![Screenshot 2023-08-13 at 14.06.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390133/02be8646-339f-3a75-8a90-0d3cd32d17ed.png)


ただし、VSCodeを利用している私は PHP Intelephense 拡張機能を入れても補完が聞きませんでした😇 残念

> • Reads **PHPStorm metadata** for improved type analysis and suggestions.
https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client
> 

この記載があったので効くと期待したのですが。。ｗ

<br>

## 参照

- https://github.com/NaoyaMiyagawa/cakephp4-ide-helper-demo
- https://github.com/dereuromark/cakephp-ide-helper