[Laravel] IDEによるコード補完まとめ

More than 1 year has passed since last update.

ほぼ自分用メモ

Laravel は Facade 使いまくりで初期状態ではIDEでコード補完できない。


どうやるの

IDE でコード補完用のファイルを生成してくれる神ライブラリがあるのでこれを使う。

barryvdh/laravel-ide-helper

上記のライブラリでできることは下記3つ


  • Facade を使ったコード補完ファイルの生成

  • データベースから生成したEloquent\Modelクラスに対してプロパティアクセスの為のコード補完ファイルの生成

  • コンテナから取得したオブジェクトに対してコード補完ファイルの生成(PhpStorm限定)

生成方法は下記の2つ


  • ServiceProvider に登録し、アプリケーションの実行毎に最新のコード補完ファイルを生成する

  • コマンドラインから手動で生成する

ServiceProvider に登録する方法は常に最新のものが生成されるメリットはありそうなものの、

開発中のオーバーヘッドが大きくなりそうなので、本記事ではコマンドラインから手動生成のみ扱う

また、生成オプション等は色々指定できるが、本記事ではよく使いそうなものだけ抜粋

詳しくはライブラリのDocument参照。


下準備

例のごとく composer でライブラリをインストールする。

composer require --dev barryvdh/laravel-ide-helper

Model のプロパティ補完を行う場合は doctrine/dbal が必要なのでこちらもインストール。

composer require --dev doctrine/dbal


Facade の補完

php artisan ide-helper:generate を実行する。

$ php artisan ide-helper:generate

A new helper file was written to _ide_helper.php

これだけで_ide_helper.phpというファイルが生成され、

IDEに読み込ませるとFacadeのコード補完ができるようになる。


Model のプロパティ補完

仕組み的には doctrine/dbal を使い実際にデータベースにアクセス、

各テーブルのカラムを判別しコードに落としている。

php artisan ide-helper:model を実行すると下記の通り確認のプロンプトが出る。

$ php artisan ide-helper:model

Do you want to overwrite the existing model files? Choose no to write to _ide_helper_models.php instead? (Yes/No): (yes/no) [no]:

yes … 既に存在している Model クラスに対してプロパティのアノテーションを追加する

no(default) … 別ファイル (_ide_helper_models.php ) を生成する

yes の場合はこんな感じの phpDoc が各モデルに追記される。

namespace App;

use Illuminate\Database\Eloquent\Model;

/**
* App\User
*
* @mixin \Eloquent
* @property int $id ID
* @property string $user_name ユーザー名
* @property \Carbon\Carbon|null $created_at 登録日時
* @property \Carbon\Carbon|null $updated_at 最終更新日時
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUserName($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUpdatedAt($value)
*/

class User extends Model
{
/** ~~ 略 ~~ **/
}

ちなみにModelディレクトリを変更している場合は--dirオプションで相対パスを指定する必要がある。

php artisan ide-helper:models --dir="path/to/models" --dir="app/src/Model"


コンテナから取得したオブジェクトのコード補完

!! PhpStorm限定 !!

まず何が可能になるか分かりにくいと思うのでサンプル。

<?php

$router = app('url');
$router->route('name'); // \Illuminate\Routing\UrlGenerator のコード補完ができる

$logger = app('log');
$logger->warning('わーにんぐ!'); // \Illuminate\Log\Writer のコード補完ができる

下記の記事が詳しい。

PhpStorm の PHPSTORM_META でサービスロケーターとかを入力補完

PhpStormのメタファイルを php artisan ide-helper:meta で生成してくれる。

$ php artisan ide-helper:meta

A new meta file was written to .phpstorm.meta.php


所感


  • PhpStorm 強い

  • DIコンテナって命名が嫌になった。使う側がDIとして使うかサービスロケーターとして使うかだから、ただのコンテナでいいやん的な


おまけ)なんでコード補完できないの

下記4パターンはほぼ等価な動き。

下3つはエイリアスなのでおまけで書いたようなもんだけど問題は一番上。

なんせ\DBなんてクラスは存在しない

公式マニュアルでもバリバリこの書き方を使っていて、当然のごとくコード補完ができない。

\DB::select('select * from users where active = ?', [1]);

app('db')->select('select * from users where active = ?', [1]);

\Illuminate\Container\Container::getInstance()->make('db')

->select('select * from users where active = ?', [1]);

$app = \Illuminate\Foundation\Application::getInstance();

($app['db'])->select('select * from users where active = ?', [1]);

どうなってるかというと以下のような流れ



  1. config/app.phpaliasesclass_aliase() 関数に登録される


  2. \DB が呼ばれると 1 で登録した \Illuminate\Support\Facades\DB が呼ばれる

  3. 存在しないstatic関数が呼ばれているので Illuminate\Support\Facades\DB の親クラス(\Illuminate\Support\Facades\Facade) の __callStatic()マジックメソッドが呼ばれる

  4. 3 のマジックメソッド内で サービスロケーター内の 'db' が呼ばれる
    (Illuminate\Support\Facades\DBにアクセサとして記載されている)。

  5. 4 で呼ばれたオブジェクトの select メソッドが呼ばれる。

サービスロケーターでは既に ServiceProvider で 'db' が登録済になっているので非常に簡略化して記述することが可能。

余談だけどサービスロケータを簡略化して呼び出すことをFacadeと呼んでいて、デザインパターンの Facade じゃない気がする…