人気のPHP WEBアプリケーションフレームワークLaravelのTipsを記録していきます

Laraelのモデルでグローバルスコープ、ローカルスコープを動的なパラメーターでセットする

● Laravelのモデルの「スコープ」 とは

Laravelのモデルのスコープとは簡単にいうと SQL文の「 WHERE aaa = 'bbb'」みたいなWHERE句 なのですが、

・「User」モデルの中の管理者フラグを持つものだけを取り扱う
・「User」モデルが既にあるときに、現在削除されてないユーザー( WHERE is_deleted = 0 )を「Activeuser」モデルとして作成する。

みたいなところで使います。
その時に使うのが モデルの「スコープ」です。

好きな時につけたり外したりできる「ローカルスコープ」と
基本的につけっ放しの「グローバルスコープ」があります。

● グローバルスコープの作成方法(A. スコープクラスを作成して使う場合)

例:自分(ログインしているユーザー)と同じチームIDを持つという条件を
( Inmyteam )というグローバルスコープとして作成して、モデルに適用します。

1. グローバルスコープの作成

/app/Scopes/Inmyteam.php

<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

class Inmyteam implements Scope
{
    /**
     * 自分のチーム内のユーザーに限定するスコープ
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        return $builder->where('team_id', '=', Auth::user()->team_id);
    }
}

2. モデルファイルから呼び出す。

app/User.php のメソッドに下記の boot() メソッドを追加する

use App\Scopes\Inmyteam;
    protected static function boot()
    {
        parent::boot();
        // スコープ「Inmyteam」を適用
        static::addGlobalScope(new Inmyteam);
    }

以上です。簡単ですね。
なおグローバルスコープに変数は渡せないようなので、ダイナミックに変わる条件(動的なパラメーター)を指定したい場合はセッションなど別のルートから取って来ましょう。
取れない場合はローカルスコープで設定します。

引用: https://goo.gl/Sk2F26

● グローバルスコープの作成方法(B. クロージャを使って記述する方法)

モデルファイル内に記述します。 利点は初めてLaravelを触る方にも見落としがない、という点と記述が楽な点です。

app/User.php のメソッドに下記の boot() メソッドを追加し、その中に直接記述する

    // /**
    //  * boot method
    //  * @return void
    //  */
    protected static function boot()
    {
        parent::boot();

        // GlobalScope
        static::addGlobalScope('report_start', function(\Illuminate\Database\Eloquent\Builder $builder){
            $builder->where('team_id', '=', Auth::user()->team_id);
        });

    }

● ローカルスコープの作成方法

引用: https://goo.gl/Wfvuka

1. ローカルスコープの作成

モデルファイルの中に直接書けばOK。 ローカルスコープはメソッドに引数を渡せます。

例) あるショップ内の商品に限定するスコープを作成する

app/Items.php

    /**
     * ローカルスコープ : ->inShop(<id>) で あるショップ内の商品に限定する
     *
     * @param    \Illuminate\Database\Eloquent\Builder    $query
     * @return   \Illuminate\Database\Eloquent\Builder
     */
     public function scopeInShop($query, $shop_id)
     {
         return $query->where('shop_id', '=', $shop_id);
     }

2. ローカルスコープの呼び出し

shop_id が 99 な商品を全件取得

Item::inShop(99)->all()

実は

Item::inShop(99)
Item::inshop(99)

どちらも使うことができますが、同じようにキャメルケースで使用することをお勧めします。

No.1305
09/11 17:03

edit