Laravel クエリの切り出し、ローカルスコープ
クエリの切り出し
コントローラでの記述を無くし、ファットコントローラを防ぐ為、モデルに共通クエリ制約(ローカルスコープ)の定義する。 readouble.com
ローカルスコープ
お作法として、メソッドの頭にscope
とつけて引数に$query
とし、戻り値に$query
と書く必要がある。
※スコープの中では->get
や->pagenate
などは書かない。そこでクエリ処理がが止まる為
コントローラーで使う場合はメソッド名のscopeを外した名前を書く。
モデル
<?php public function scopeAvailableItems($query) { //t_stocksテーブルのproduct_idをグループ化して、Havingでquantityを結合 $stocks = DB::table('t_stocks') //Laravelの場合、select内でsumを使うため クエリビルダのDB::rawで対応する ->select('product_id', DB::raw('sum(quantity) as quantity')) ->groupBy('product_id') ->having('quantity', '>', 1); return $query ->joinSub($stocks, 'stock', function($join){ //さらにproductとshopテーブルをjoinで結合 $join->on('products.id', '=', 'stock.product_id'); }) //shopsテーブルのidとproductsテーブルのproduct_idを結合 ->join('shops', 'products.shop_id', '=', 'shops.id') ->join('secondary_categories', 'products.secondary_category_id', '=', 'secondary_categories.id') //imagesテーブルのidとproductsテーブルのimage1を結合 ->join('images as image1', 'products.image1', '=', 'image1.id') //shopsとproductsのis_sellingがtrueならgetする ->where('shops.is_selling', true) ->where('products.is_selling', true) //複数のテーブルを紐付ける為、同じ列名が存在するのでテーブル名.列名 as 名前のように指定する。 ->select('products.id as id', 'products.name as name', 'products.price' ,'products.sort_order as sort_order', 'products.information', 'secondary_categories.name as category' ,'image1.filename as filename'); }
- WHERE・・・「GROUP BY」の影響の前に条件が適応
- HAVING・・・「GORUP BY」の影響のあとに条件が適応
コントローラー
<?php public function index() { $products = Product::availableItems()->get(); return view('user.index', compact('products')); }