Laravel

【Laravel】ローカルスコープについて解説

こんにちは!ともです(@_tomo_engineer)!

今回はLaravelの強力な機能であるクエリスコープの1つローカルスコープについて解説します。

結論から先に

  • ローカルスコープによりクエリチェーンを再利用できる
  • 上記の再利用により、コントローラーを簡潔に書ける
  • スコープ名からクエリの内容を理解できる
  • 一括で修正可能

目次

  • ローカルコープとは
  • ローカルスコープの利点
  • ローカルスコープの作成方法

ローカルコープとは

ドキュメントには以下のように説明されています。

ローカルスコープによりアプリケーション全体で簡単に再利用可能な、一連の共通制約を定義できます。例えば、人気のある(popular)ユーザーを全員取得する必要が、しばしばあるとしましょう。スコープを定義するには、scopeを先頭につけた、Eloquentモデルのメソッドを定義します。

スコープはいつもクエリビルダインスタンスを返します。

つまり、ローカルスコープによって一連のクエリをまとめて管理する事ができます。

例えば、クラスの生徒の内、180cm以上の男子を検索するクエリを考えてみます。

$query = Student::where('tall', '>', 1.8)->where('gender', 1);
  • 体育祭のチーム分け
  • 写真を取るときは後ろに並ぶ
  • などなど

背の高い男子生徒を頻繁に絞り込む必要があるかと思います

これをローカルスコープで絞り混むと以下のようになります。

$query= Student::tallMenStudents();

ローカルスコープを利用する事で簡潔に記述できました。

長い一連のクエリをローカルスコープにまとめる事でコントローラの肥大化を抑える事ができます。

次のコントローラをご覧ください。

$student = Student::where('tall', '>', '1.8')
                         ->where('gender', 1)
                         ->where('degree', 2)
                         ->where('class', A)
                         ->where('club', 1)
                         ->get();

あるクラブに所属する身長1.8[m]以上で2年A組の男子を検索するクエリです。

このような長いクエリが頻繁に利用される場合、ローカルスコープはさらに強力です。

これだけがローカルスコープの利点ではありません。

ローカルスコープ名が何をしたいか表している

私はこのローカルスコープにtallMenStudentsと名付けました。

このスコープ名を見れば

背の高い男子学生を取得したいのだなと

と簡単に開発者に伝える事ができます。

再利用できる

コントローラ1(体育祭での背の高い男子の検索)

コントローラ2(写真を取る際の背の高い男子の検索)

コントローラ3(女子にモテる、背の高い男子を検索)

などなど

多くのコントローラ内で

$query = Student::where('tall', '>', 1.8)->where('gender', 1);

$query= Student::tallMenStudents();

と記述し、再利用可能です。

修正が容易

あなたが開発者で背の高い基準が1.9[m]になったと想像して下さい。

クエリチェーンで開発した場合、全てのコントローラ内のこのクエリを1.8[m]から1.9[m]に変更しなければなりません。

全部修正しないとあかんやん・・・

大規模になればなるほど、この修正は大変なものになります。

しかし、

ローカルスコープを利用した場合、ローカルスコープの1.8[m]を1.9[m]に修正するだけで全てが更新されます。

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

ローカルスコープはモデルに作成します。

$query= Student::tallMenStudents();

この例に示したように、tallMenStudentsというローカルスコープはStudentモデルのメソッドである事が分かります。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    public function scopeTallMenStudents($query)
    {
        return $query->where('tall', '>', 1.8)->where('gender', 1);
    }
}

モデルのクラスにscopeTallMenStudents($query)を作成します。

tallMenStudentで呼び出してたのに、何そのscopeは?

ローカルスコープの命名には次の規則があります。

scopeを先頭に着けた、Eloquentモデルのメソッドを定義する

よってtallMenStudents => scopeTallMenStudentとなる訳です。

実装は極めて簡単です。

まとめ

ローカルスコープでクエリチェインをまとめる方法とその利点について説明しました。

ローカルスコープを利用する事でより保守しやすいシステムになりますので、適切な場所で利用していきましょう。