【Laravel】グローバルスコープの設定を外す方法

  • 2023年2月17日
  • 2023年2月17日
  • Laravel

 Laravel にはグローバルスコープという仕組みがあります。これは Laravel の Eloquent(データベーステ-ブルに対応するリポジトリ、ファクトリ機能を持ち、レコードがインスタンスとして表現されるモデル)に備わっている機能でグローバルスコープとして Eloquent に登録されたクエリはその Eloquent を介して発行されるクエリすべてに付与されます。例えばこの機能は論理削除に使われます。常に論理削除済みであるか否かをクエリに含めてくれるため論理削除判定の WHERE 句を忘れることがありません。

Eloquentの準備 9.x Laravel#グローバルスコープ

 グローバルスコープは便利なのですが時としてそのグローバルスコープの適用範囲内であってもグローバルスコープを無視したい時があります。単品のクエリ内で無視する方法は Laravel で用意されており、次の様にできます。

// @see https://readouble.com/laravel/9.x/ja/eloquent.html#header=%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97
User::withoutGlobalScope(AncientScope::class)->get();

 しかしながら残念なことに一度設定されたグローバルスコープを設定そのものから除外する機能は備わっていません。設定を解除すれば解除後はなにもしなくとも常にグローバルスコープが適用されない様にして欲しい場合もあります。これは次のコードでできます。

class User extends Model
{
     /**
     * グローバルスコープの設定を解除する
     * @param  Scope|\Closure|string $scope addGlobalScope で指定したスコープのキー
     * @return void
     */
    public static function removeGlobalScope(Scope|\Closure|string $scope): void
    {
        // @see \Illuminate\Database\Eloquent\Concerns\HasGlobalScopes::addGlobalScope
        // addGlobalScope で定義されている場所を unset することで設定を解除する 
        if (is_string($scope)) {
            unset(static::$globalScopes[static::class][$scope]);
        } elseif ($scope instanceof \Closure) {
            unset(static::$globalScopes[static::class][spl_object_hash($scope)]);
        } elseif ($scope instanceof Scope) {
            unset(static::$globalScopes[static::class][get_class($scope)]);
        } else {
            throw new \InvalidArgumentException('Global scope must be an instance of Closure or Scope.');
        }
    }
}

 Laravel の内部実装に踏み込むと addGlobalScope はモデルクラスの静的プロパティ $globalScopes にスコープ処理を加える、というメソッドです。グローバルスコープ設定の解除をしたいのであれば。このプロパティから解除したいグローバルスコープを選び unset すればいいです。

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

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

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

CTR IMG