スコープとは
Eloquentのスコープは、クエリに対する制約をまとめて再利用できる仕組みです。スコープには2種類あります。ローカルスコープ
定義
ローカルスコープは、モデルのメソッドに#[Scope] アトリビュートを付与して定義します。
#[Scope] アトリビュートは Illuminate\Database\Eloquent\Attributes 名前空間にあります。PHP 8.0以降のネイティブ構文です。使い方
定義したスコープは、メソッドとして呼び出せます。チェーンもできます。パラメータの受け渡し
スコープメソッドの第2引数以降に追加のパラメータを定義できます。orWhere との組み合わせ
スコープを orWhere でつなぐとき、論理グループが必要になる場合があります。
グローバルスコープ
仕組み
グローバルスコープはIlluminate\Database\Eloquent\Scope インターフェースを実装したクラスです。このインターフェースは apply メソッド1つだけを要求します。
apply メソッドの中でクエリビルダーに制約を追加します。
グローバルスコープクラスの作成
make:scope コマンドで雛形を生成します。
app/Models/Scopes/ActiveScope.php が生成されます。
モデルへの適用
1
#[ScopedBy] アトリビュートで登録(推奨)
Laravel 13では 複数のスコープを配列で指定できます。
#[ScopedBy] アトリビュートを使うのが最もシンプルです。2
booted() メソッドで手動登録
booted メソッドをオーバーライドして addGlobalScope を呼び出す方法もあります。User::all() など全クエリに自動で WHERE is_active = 1 が付きます。
無名クロージャによるグローバルスコープ
クラスを別ファイルに作るほどでもない単純なスコープは、クロージャで定義できます。グローバルスコープの除外
特定のクエリではスコープを無効にしたい場面があります。フレームワーク内部: SoftDeletingScope
Laravel標準のSoftDeletes トレイトがグローバルスコープをどう活用しているかを見ると、実装パターンが分かります。
SoftDeletingScope は Scope インターフェースを実装しています。
withTrashed() の実装を見る
withTrashed() の実装を見る
withTrashed() は実際には withoutGlobalScope($this) を呼び出しています。つまり SoftDeletingScope 自身を除外することで、削除済みレコードも取得できるようにしています。onlyTrashed() も同様に、スコープ自身を除外した上で whereNotNull('deleted_at') を追加しています。実践的なユースケース
マルチテナント: テナントIDによる自動絞り込み
SaaSアプリケーションでは、全クエリにテナントIDのフィルタを自動適用することが重要です。Post::all() を呼ぶだけで、認証中のユーザーのテナントデータだけが返ります。
公開/非公開フィルタ
管理画面では非公開の投稿も表示したいが、フロントエンドでは公開済みのみ表示したい場合です。withoutGlobalScope でスコープを除外します。
select ではなく addSelect を使う
次のステップ
Eloquent カスタムキャスト
属性の変換ロジックをカスタムキャストとして実装し、Value Objectパターンを活用する方法を学びます。