Laravelを静的解析フレンドリにしてPhpStormで快適に開発するテクニック

Laravelを静的解析フレンドリにしてPhpStormで快適に開発するテクニック

Laravelから魔法を取り除いて静的解析フレンドリにして、PhpStormで快適に開発するテクニックを紹介したいと思います。静的解析フレンドリにすることは、PhpStormだけではなく、Larastanなどの静的解析ツールなどでも、より良い解析結果を返してくれるようになるかと思います。

Facadeを使用する場合にAliasを使用しない

Facadeを使用する場合にAliasを使用しないようにしましょう。PhpStormはAliasに対応していため、Facadeクラスを見つけることができません。Aliasを使用せず、namespaceをきちんと書くことでFacadeクラスを見つけることができます。

ビルトインのFacadeにはPHPDocが書かれており、Facadeのメゾットを保管することが出来ます。

例:

- \App::environment()
+ \Illuminate\Support\Facades\App::environment()

Model::queryを使用してクエリー実行する

Eloquent ORMを使用するときは、queryメソッドから開始することでメソッドを保管することができるようになります。

例:

- User::where('created_at', '<', now())->get();
+ User::query()->where('created_at', '<', now())->get();

Model::newEloquentBuilderをオーバーライドして独自QueryBuilderを定義する

ローカルスコープ(scope***)を使用せずに、newEloquentBuilderメソッドをオーバーライドして独自QueryBuilderを定義すると静的解析が可能になります。独自定義したQueryBuilderは、通常時と同様にModelのグローバルスコープやローカルスコープも使用することが出来ます。

例:

namespace App\Models;

use App\EloquentBuilders\BookBuilder;
use Illuminate\Database\Eloquent\Model;

/**
 * @method static BookBuilder query()
 */
class Book extend Model
{
    /**
     * @param \Illuminate\Database\Query\Builder $query
     *
     * @return BookBuilder<self>
     */
    public function newEloquentBuilder($query): BookBuilder
    {
        return new BookBuilder($query);
    }
}
namespace App\EloquentBuilders;

use App\Models\Book;
use Illuminate\Database\Eloquent\Builder;

/**
 * @template TModelClass of Book
 * @extends Builder<TModelClass>
 */
class BookBuilder extends Builder
{
    public function wherePublished(): static
    {
        return $this->where('published_at', '<=', now());
    }

    public function whereLikeTitle(string $keyword): static
    {
        return $this->where('title', 'LIKE', '%' . $keyword . '%');
    }
}
Book::query()
    ->wherePublished()
    ->whereLikeTitle($keyword)
    ->orderBy('published_at', 'DESC')
    ->get();

Accessor/Mutatorではなくメソッドを直接使用する

Laravel 8以前のAccessor/Mutatorの書き方であるget***Attribute / set***Attributeを使用する場合で、データの読み書きをする際に、Accessor/Mutatorを使用せずにメソッドを直接使用することで、静的解析することができるようになります。

例:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $appends = [
        'full_name',
    ];

    public function getFullNameAttribute(): string
    {
        return sprintf('%s %s', $this->first_name, $this->last_name);
    }
}
- $user->full_name;
+ $user->getFullNameAttribute();

Laravel IDE Helperについて

LarastanはLaravel IDE Helperを使用しているとバグが発生することがあるようです。そのため、Larastanを使用するのであれば、Laravel IDE Helperはインストールしない方が良いかもしれません。

おわりに

newEloquentBuilderメソッドをオーバーライドするのはお行儀が悪そうに思えますが、独自QueryBuilderを定義することによって、Repositoryパターンのように関心事を分けることができるので、静的解析関係なくおすすめです。