【Laravel】public static function hogehoge()とpublic function scopeHogehoge()の使い分け

 LaravelのEloquentにはクエリビルダでチェーンを組むための命名規則に従ったメソッド作成方法があります。scopeHogehoge()とするとModel::hogehoge()とするとクエリビルダが走ります。この状態のまま次のようにチェーンを組めるのが利点です。

User::hogehoge()->orderBy('fuga')->limit(30);

 検索などでクエリの一部を使いまわしたい時などとても助かります。助かるのですが、この手法はモデルにも継承元であるEloquentにも記述されていないメソッドを呼び出しており、IDEのヘルパが効かず、警告も出力されます。次のようにコメントを記述することで対策できますが、コメントを経由して改めてscopeHogehoge()を検索する必要があります。

/**
 * @method static Builder|User newModelQuery()
 * @method static Builder|User newQuery()
 * @method static Builder|User query()
 * @mixin Eloquent
 *
 * @method static Builder|User Hogehoge()
 */
class User extends Model
{
    public function scopeHogehoge($query)
    {
        return $query->where('なんやかんや');
    }
}

 クエリが増えるにつれどんどんコメント→実際の記述と追うのが面倒になりだします。自分の知る使えそうな小技は二つです。一つはコメントの長大化の弊害がありますが次のようにコメントすることです。@seeはによってIDEはジャンプができる様になります。PhpStormならCtrl+Bです。

/**
 * @method static Builder|User newModelQuery()
 * @method static Builder|User newQuery()
 * @method static Builder|User query()
 * @mixin Eloquent
 *
 * @method static Builder|User Hogehoge()
 * @see   \App\Models\Eloquents\User::scopeHogehoge
 */
class User extends Model
{
    public function scopeHogehoge($query)
    {
        return $query->where('なんやかんや');
    }
}

 もう一つはstaticなクエリビルドメソッドを作ることです。Model::からクエリビルドする時はEloquentクラス中の次のメソッドが呼ばれています。これを使うことで任意のクエリをグローバルスコープ等欠けさせることなく使えます。staticなのでクエリビルド用の別クラスを用意することも簡単です。

class Eloquent
{
...
    /**
     * Begin querying the model.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public static function query()
    {
        return (new static)->newQuery();
    }
    /**
     * Get a new query builder for the model's table.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function newQuery()
    {
        return $this->registerGlobalScopes($this->newQueryWithoutScopes());
    }
...
}

 次が例です。再利用するあてのないメソッドならあと腐れなくstaticにできます。またこのstaticメソッドでビルダーを返せば、後にクエリビルド用のメソッドチェーンを続けることもできます。

public static function hogehoge($name)
{
    return self::query()->whereName($name)->first();
}
>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG