Laravelのクエリスコープについて

laravel-scopes Laravel

余談

いきなり余談かい…

ちょっと付き合っていただけると嬉しいです。笑

みなさん最近調子はどうですか?

勉強。進んでますか?

目標に向かってブレずに勉強できてますか?

残念ながら私は眠すぎて本当はもう眠りたいです笑

でも!!!私は5年以内にフルスタックエンジニアになることを目標にしています。

ド直球に言うと強強エンジニアとしていろんな場面で活躍したいです!

ネットで記事を発信している人や、OSS開発で活発な活動をされている方。

何かしらのイベントで登壇をしたり、書籍を出したり。

正直言って全部興味あります!(でも体は一つしかない…)

なのでひとまずWeb開発で必要となるものから順に身につけていきたい思ってます!

だいぶ話がずれてしまいましたね笑

では本題に戻りましょう!

クエリスコープについて

クエリスコープはEloquentモデルにカスタムのクエリロジックを組み込む方法の一つです。

コードの再利用性と可読性を向上させるために使用されます。

クエリスコープは、特定のクエリに対して定義できるメソッドで、通常はデータベースからの特定のフィルタリングや条件付きクエリを簡潔に表現するために用いられます。

クエリスコープは全部で2つあるので、それぞれで詳しく説明します!

  • グローバルスコープ
  • ローカルスコープ

グローバルスコープ

モデルに適用される全てのクエリに自動的に適用されるスコープです。

データベースからの取得結果を常にフィルタリングしたい場合に便利な機能です。

例えば、論理削除されたものを除外するためによく使われます。

さっそく作ってみましょう!

新しいグローバルスコープを作成するためには、コマンドでスコープクラスを作成する必要があります。

php artisan make:scope ActiveScope

すると、app\Models\Scopesの中にAncientScopeクラスが自動生成されます。

<?php

namespace App\Models\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class ActiveScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     */
    public function apply(Builder $builder, Model $model): void
    {
        //
    }
}

今回は「activeのカラムが1であるデータのみ抽出する」というスコープを作成する場合、このように書きます。

public function apply(Builder $builder, Model $model): void
{
    $builder->where('active', 1);
}

モデルに対してグローバルスコープを適用させるためにはモデルの booted メソッドでスコープを登録します。(実は私も使うのは初めて…笑)

以下コードをモデルクラスの中に入れてください!

protected static function booted()
{
    static::addGlobalScope(new ActiveScope);
}

これでスコープの実装は完了です!

コントローラー側でUser::all();などでモデルを呼び出し、デバッグバーでクエリを確認してみると以下のようなSQLを確認することができます!

select * from `users` where `active` = 1

簡単ですね!システム内で必ず加える条件を指定する場合はグローバルスコープを使うのが適当ですね!

ローカルスコープ

ローカルスコープは、モデル内にscopeから始まるメソッド名を定義して作成します。

scopeメソッドはクエリビルダのインスタンスを受け取り、その上に条件を追加して返す形になります。

メソッド名の先頭には必ずscopeを付け、クエリ実行時にはその部分を省略して呼び出します。

// モデル側でメソッド名のscopeを先頭に置く
public function scopeActive($query)
{
    return $query->where('active', 1);
}

// コントローラー側ではUserモデルのscopeを省いたactiveとして指定
$activeUsers = User::active()->get();

このactive()を指定しないとscopeActiveは適用されないので、コントローラー側で臨機応変にON/OFFが可能となると言うことです!

超絶便利ですね!再利用も可能、モデル側でscopexxxxの中身を変えるだけで適用している箇所全てに反映されるので、保守性も高まるなと思いました!!

最後に

みなさんどうでしたか?

クエリスコープ!使う機会があればどんどん使っていきたいですね!

さて、、、

次は何を勉強しようか🤔

コメント

タイトルとURLをコピーしました