46
36

More than 3 years have passed since last update.

Laravelでスコープ

Last updated at Posted at 2020-03-20

定義方法

scope名は必ず最初にscopeを名前の初めに付ける必要がある.
・scopeUserName
・scopeBookSerialNo
上記のようにスコープ名をつける。

public function scope+名前($query, 引数)
    {
      # 処理内容
      return 絞り込んだビルダ(検索条件)
    }

ローカルスコープ

定義したメソッドを呼び出す場合に実行することができるスコープ。
逆に定義していれば自動的にスコープメソッドが実行されるものはグローバルスコープ。

Person.php
# scopeの定義
  public function scopeNameEqual($query, $str)
  {
    return $query->where('name', $str);
  }
PersonController.php
  public function search(Request $request){
    $input_val = $request->input;
    $item = Person::NameEqual($input_val)->first();
    $params = ['input' => $input_val, 'id' => $request->id, 'item' => $item];
    return view('person.find', $params);
  }

スコープを複数繋げて利用する

2種類のスコープを定義

Model.php
  // $min(変数の値)以上のageを検索するスコープ
  public function scopeAgeGreaterThan($query, $min)
  {
    return $query->where('age', '>=', $min);
  }

  // $max(変数の値)以下のageを検索するスコープ
  public function scopeAgeLessThan($query, $max)
  {
    return $query->where('age', '<=', $max);
  }

下記サンプルのように条件をつなげて使う

例:ageが "リクエストで受け取った値" 〜 "値+10" の間のデータを取得するスコープ
()

Controller.php
    $min = $request->input * 1;
    $max = $min + 10;
    $items = Person::ageGreaterThan($min)->ageLessThan($max)->get();

グローバルスコープ

明示的にメソッドを呼び出さなくても自動的にスコープの検索ありきで検索が実行される

1.use Illuminate\Database\Eloquent\Builder; ←Builder使えるようにする
2.bootメソッドでモデルの初期化を行う
3.bootメソッド内でaddGlobalScopeクロージャを書く
4.addGlobalScopeクロージャの中でスコープの処理を定義していく

こうすることでモデルクラスでbootメソッドがオーバーライドされる

Model.php
use Illuminate\Database\Eloquent\Builder;

class Person extends Model
{
  // グローバルスコープ定義 //
  protected static function boot()
  {
    parent::boot();
    static::addGlobalScope('age', function(Builder $builder){
      $builder->where('age', '>', 20);
    });
  }
  ...
  ...
  ...
}

Scopeクラス作成(グローバルスコープ)

複数のモデルや、その他のプロジェクトなどでも利用されるような汎用性の高い処理はScopeクラスを使うと便利.

Scopeクラスの作成

1.Scopesディレクトリ(名前は任意)を作成。
2.Scopeクラスの作成(仮でScopePersonというクラスにします)

常に20歳より年上のみを取得するスコープを作成するため下記コード記載

Scopes/ScopePerson.php
<?php
namespace App\Scope;

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

class ScopePerson implements Scope
{
  public function apply(Builder $builder, Model $model)
  {
    $builder->where('age', '>', 20);
  }
}

Model側でグローバルスコープを定義
・useしてScopePersonを参照できるようにしたらstatic::addGlobalScope(New ScopePerson)してあげるだけ

Model.php
use App\Scope\ScopePerson;

  // グローバルスコープ定義 //
  protected static function boot()
  {
    parent::boot();
    static::addGlobalScope(New ScopePerson);
  }

こうすることで
Person::all();等で複数データを取得した場合に自動的にageが20以下のものはフィルターされる

46
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
36