softonsofa.comからの記事「 Eloquent関係の調整 -hasMany 関係を効率的に取得する方法 」の記事の無料翻訳を紹介します。モデルリレーションシップを使用する場合は、受け取ったアイテム(コメントやいいね!など)の数をカウントすることをお勧めします。 明らかにこれを行う方法はありますが、特にモデルのコレクションとそれらの関係をダウンロードする場合は必ずしも効果的ではありません。
さて、それについて私たちにできることを教えてください。
hasMany関係public function comments() { return $this->hasMany('Comment'); }
最も簡単な方法は、次の2つのメソッドのいずれかを使用することです(PostモデルのgetCommentsCount型のメソッドにラップされる可能性があります)。
[1] > $post = Post::first();
ただし、これはまだ最善の解決策ではありません。
- $ post-> comments-> count(); コレクションをロードし、その要素の数を返します。数量だけを取得する必要がある場合は適切ではありません。
- $ post->コメント()-> count(); 良いことに、コレクションはロードされませんが、メソッドを実行するたびにリクエストを送信します。
投稿のコレクションを取得してコメントをカウントする必要がある場合は、もちろん、join、groupByなどを使用できますが、誰が気にしますか? なぜこのようなものを書く必要があるのでしょうか?
$posts = Post::leftJoin('comments', 'comments.post_id', '=', 'posts.id') ->select('posts.*', 'count(*) as commentsCount') ->groupBy('posts.id') ->get();
エレガントなEloquentスタイルの構文を好む場合。
$posts = Post::with('commentsCount')->get();
これがまさに私たちが必要とするものです。最後にやってみましょう。 Eloquentにコメントの数をプリロードさせるには、Relationオブジェクトを返すメソッドをモデルに作成する必要があります。
public function comments() { return $this->hasMany('Comment'); } public function commentsCount() { return $this->comments() ->selectRaw('post_id, count(*) as aggregate') ->groupBy('post_id'); }
確かに機能しますが、すべてをそのままにしておくと私は自分ではありません。
$post = Post::with('commentsCount')->first(); $post->commentsCount; $post->commentsCount->first(); $post->commentsCount->first()->aggregate;
コードを少し改善しましょう。
- 1つの要素を持つコレクションを返すことを避けるために、hasManyの代わりにhasOneを使用します
- コメントをカウントするためにアクセス方法を使用します
public function commentsCount() { return $this->hasOne('Comment') ->selectRaw('post_id, count(*) as aggregate') ->groupBy('post_id'); } public function getCommentsCountAttribute() { if ( ! array_key_exists('commentsCount', $this->relations)) $this->load('commentsCount'); $related = $this->getRelation('commentsCount'); return ($related) ? (int) $related->aggregate : 0; }
これで、作業がより簡単で美しくなりました。
$post = Post::first(); $post->commentsCount;