Eloquentのcount()
の関数を使用して、DBのレコード数を数える作業はよく起こります。
例えば、前回の画像の件では、商品product
のレコード1に対して商品画像product_image
レコードが複数あるという、1対多の関係。そこでは、商品を削除するときに商品画像がないかをチェックする必要あります。画像のレコードがあるなら、削除を拒否あるいはユーザーに削除してよいか尋ねるということになります。
この場合は、商品画像があるかないかは、count()
するのが一番。しかし、Eloquentではいろいろなカウントのコードの仕方があります。
今回は、これを説明するために、コントローラに特別にメソッドを作成してみました。
namespace App\Http\Controllers\User; use App\Http\Controllers\Controller; use App\Product; use App\ProductImage; class ProductController extends Controller { public function getCount(Product $product) { $count1 = ProductImage::where('product_id', $product->product_id)->get()->count(); $count2 = ProductImage::where('product_id', $product->product_id)->count(); $count3 = $product->product_images->count(); $count4 = $product->product_images()->count(); return sprintf("<pre>count1 = %d\ncount2 = %d\ncount3 = %d\ncount4 = %d\n</pre>", $count1, $count2, $count3, $count4); } }
最初の、$count1
は、whereでproduct_imageのレコードを絞ってgetして、それらのレコードをcount()
します。しかし、getしたのはIlluminate\Database\Eloquent\Collection
のオブジェクトであり、取得したレコードのデータすべてが入っています。2,3のレコード数なら問題ないけれど、1000とかあれば、それだけのデータがメモリーに入るわけで、単にレコード数が必要なのにとんでもない浪費です。
それに比べて次の、$count2
は、SQLクエリのCOUNT(*)
を使用するので、取得するのは、まさに1つのカウント数だです。$count1
とは大きな違いです。
さて、Product
のモデルには、
namespace App; use Illuminate\Database\Eloquent\Model; class Product extends Model { ... public function product_images() { return $this->hasMany('App\ProductImage'); } }
ProductImage
とのリレーションが定義されています。
これを利用したのが、先の$count3
です。コードすっきりしましたね。しかし、ここ注意してください。この取得のしかたは、先の$count1
とまったく同じなのです。つまり、必要なレコードをすべて含んだCollection
を作成してから、それをカウント。
これを正しくクエリで実行してもらうのが、$count4
です。ちょっとした違いですね。product_images->count()
かproduct_images()->count()
か。
実際、これらの実行がどうなっているかは、実行したクエリを見ればわかります。以下は、Debugbarの結果です。
カウント数は皆同じですが、2と4では、select count(*)
ですが、1と3は、select *
となっていますね。
とても参考になる記事をありがとうございます。
現在の仕事に役立たせて頂きます。
ところで、発行したSQL(select * from `product_image` where `product_id` = `1` など)がグラフィカルに表示されているようですが、これは何というツールを使われているのでしょうか?
「かいそふと」さん
嬉しいコメントです。
ご質問の件ですが、以下を使用しています。
https://github.com/barryvdh/laravel-debugbar
私のブログでは以下で紹介されていますが、古くなっているの注意してください。
https://www.larajapan.com/tag/debugbar/
返信ありがとうございます!
是非活用させて頂きます。