最近Laravelのスコープという機能をよく使うのですが、個人的に保守性・可読性の面で結構いいなと思ってましてその紹介をいたします。
グローバルスコープとローカルスコープという括りがありますが、特にローカルスコープを推したく深堀って説明します。
(グローバルスコープはブラックボックスになりがちなので個人的には微妙です...)
scopeって?
Laravelにおけるスコープとは、Model内でよく使う検索条件に名前を付けて再利用しやすくする仕組みです。
後述する「使用例」にて挙げますが、「割引中の商品だけ絞り込む」とか他にも「品薄の商品を絞り込む」 とかよく使いそうなクエリをどっかでまとめて定義しちゃおうな考えです。
使用例
まず、定義部分ですがscope○○で関数定義します。
その中でよく使う検索条件を定義するイメージです。
※この時点ではBuilderである必要があります。get等使ってCollectionになるとそれ以降のwhereやorderbyが繋げられなくなります、、
例:割引中の商品のみ絞り込むクエリ
public function scopeOnSale($query)
{
return $query->where('is_active', true) // 有効
->where('stock', '>', 0) // 在庫あり
->where('sale_price', '>', 0) // セール価格設定あり
->whereDate('sale_start_at', '<=', Carbon::now()); // 期限内
->whereDate('sale_end_at', '>=', Carbon::now()); // 期限内
}
次に呼び出す際ですがscopeを除いた名前で呼び出します。
scopeOnSaleであればonSaleで呼び出します。
A. トップページ(セール中のものを5品取得)
$products = Product::onSale()->limit(5)->get();
B. カテゴリページ(家電のセール品を取得)
$electronics = Product::onSale()->where('category', 'appliance')->get();
A,Bどちらのパターンもscope使わずに全量書くとそれぞれ追加で記載が必要になり、保守性や可読性の面で微妙になるというわけです。
以上、クエリビルダも関数定義っぽくできるという話でした。
参考