Laravel Eloquent ORM のモデルによく使うスコープをメソッドで登録する

Qiita Laravel Advent Calendar 2018 の18日目の記事となります。furuichiです。

クエリスコープ

Laravel の Eloquent ORM では、モデルに紐づけたメソッドを使うとDBからのデータの取得がらくらくできる。

モデル名::find(主キー)

$customer = Customer::find($customer_ID)

上のコードでは、$customer_IDを主キーとして持つレコードを Customer テーブルから取得できる。 これがクエリスコープという仕組みで、デフォルトで使えるメソッドとしてはfindが有名。そのほかにオリジナルでよく使うクエリをモデルに紐づけて登録することができる。

よく使うwhere句をモデルに紐づける場合

Customer->where('address' '=' $address)->get() のようなクエリを多用する時、いちいち同じコードを書いていると冗長になるので、クエリスコープとして登録すると短く書ける。

クエリスコープの作り方・使い方

作り方

モデル名.php ファイルにメソッドを追加するだけ。上の Customer モデルを例にとって作成して見ましょう。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    protected $table = 'customer'; //参照するテーブル名

    public function scopeAddress($query, $address) //スコープのメソッド。
    {
        return $query->where('address', '=', $address);

    }
}

クエリスコープのメソッドは scopeXxx のようにscopeから始まるキャメルケースで命名します。第1引数に $query を、第2以降の引数に変数を指定します。

使い方

Controller など、任意の場所で以下のように使えます。

$address = '北海道';

$customer = Customer::address($address)->get();

scopeHoge という名前のメソッドの Hoge の部分を小文字から始める形で使います。 上のコードは、Customer->where('address' '=' '北海道')->get() というクエリを書いた時と同じ結果を取得できます。

というのを社内で共有したのですが、社内からこんあツッコミがありました。

例えば住所であれば、英語で "customer living in Hokkaido"

と表現することができますよね。その考えを反映させて、 スコープ名を $customer = Customer::livingIn('北海道'); にするとかどうでしょうか? あくまで参考です。

このツッコミで、メソッドの命名を工夫すれば自然言語を読む感覚でクエリスコープを使えそうだな、と思いました。 上記の命名方法でクエリスコープを書き直すとこうなりますね。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    protected $table = 'customer'; //参照するテーブル名

    public function scopeLivingIn($query, $address) //スコープのメソッド。
    {
        return $query->where('address', '=', $address);
    }
}

クエリスコープはより複雑な条件もメソッドとして登録できるので、頻繁に使うクエリはどんどんモデル配下のメソッドとして書いておくと全体のコードがスリムになるかもしれません。