Laravelで「コレクションの要素数を数えたい」ときは、count()メソッドを使えば1行で件数を取得できます。この記事では、Collectionの要素数を数える基本から、条件に合う要素だけを数えるfilter()->count()、値ごとの出現回数を数えるcountBy()、空判定のisEmpty() / isNotEmpty()、さらにCollectionのcount()とデータベース側で集計するQuery Builder・Eloquentのcount()の違いとパフォーマンス差まで整理して解説します。
Collectionのcount()の基本と返り値
countメソッドは、コレクション内の要素の数を整数(int)で返します。引数は不要で、コレクションに含まれる要素の総数をそのまま返します。
$collection = collect([1, 2, 3, 4, 5]);
$count = $collection->count();
echo $count; // 結果: 5
var_dump($count); // int(5)上記の例では、collect関数で配列をコレクションに変換し、countメソッドで要素の数を取得しています。返り値は必ず整数なので、そのまま比較や計算に使えます。空のコレクションに対しては0が返ります。
collect([])->count(); // 0条件に合う要素だけを数える(filter()->count())
「特定の条件を満たす要素だけ何件あるか」を知りたい場合は、filterで絞り込んでからcountを呼び出します。
$collection = collect([1, 2, 3, 4, 5]);
$count = $collection->filter(function ($item) {
return $item > 2;
})->count();
echo $count; // 結果: 3filterメソッドの引数にクロージャ(匿名関数)を渡すと、各要素に対して条件が評価され、trueを返した要素だけが残ります。その結果に対してcountを呼ぶことで「条件に合う件数」を取得できます。連想配列のキーや値で絞り込みたい場合は、whereメソッドでの条件抽出やfilterメソッドの使い方もあわせて確認してください。
値ごとの出現回数を数える(countBy)と用途の違い
countが「要素の総数」を返すのに対し、countByは「同じ値がそれぞれ何回出現したか」を集計し、値をキー・出現回数を値とした新しいコレクションを返します。
$collection = collect([1, 2, 2, 2, 3]);
$counted = $collection->countBy();
$counted->all();
// [1 => 1, 2 => 3, 3 => 1]クロージャを渡すと、その戻り値ごとに件数をまとめられます。たとえばメールアドレスのドメインごとの件数を数える、といった集計に便利です。
$emails = collect([
'alice@gmail.com',
'bob@gmail.com',
'carol@example.com',
]);
$counted = $emails->countBy(function ($email) {
return substr(strrchr($email, '@'), 1);
});
$counted->all();
// ['gmail.com' => 2, 'example.com' => 1]| メソッド | 返り値 | 主な用途 |
|---|---|---|
count() | 整数 | 要素の総数を数える |
filter()->count() | 整数 | 条件に合う要素だけを数える |
countBy() | コレクション | 値ごとの出現回数をまとめて集計する |
キーで分類してからそれぞれの件数を扱いたい場合は、groupByでグループ化してから各グループにcount()を適用する方法も使えます。
空かどうかを判定する(isEmpty / isNotEmpty)との使い分け
「件数が0かどうか」だけを知りたいときは、count()の結果を0と比較するよりも、isEmpty() / isNotEmpty()を使うほうが意図が明確です。どちらも真偽値(bool)を返します。
$collection = collect([]);
$collection->isEmpty(); // true(要素が0件)
$collection->isNotEmpty(); // false
// 件数そのものが不要で「あるか / ないか」だけ判定したい場合
if ($collection->isNotEmpty()) {
// 1件以上あるときの処理
}使い分けの目安は次のとおりです。実際に件数が必要ならcount()、有無だけを判定するならisEmpty() / isNotEmpty()を使うと、コードの意図が読み取りやすくなります。
| やりたいこと | 推奨メソッド |
|---|---|
| 件数(数値)が必要 | count() |
| 要素が0件かどうかを判定 | isEmpty() |
| 要素が1件以上あるかを判定 | isNotEmpty() |
Collectionのcount()とQuery Builder・Eloquentのcount()の違い
同じcount()でも、Collection(PHP側)で数えるのか、Query Builder・Eloquent(データベース側)で数えるのかで、処理の中身は大きく異なります。
// (1) DB側で件数だけを集計する(SELECT COUNT(*) が発行される)
$count = User::where('active', true)->count();
// (2) 全件を取得してからPHP側(Collection)で数える
$count = User::where('active', true)->get()->count();(1) はEloquent/Query Builderのcount()で、データベースにSELECT COUNT(*)を発行し、件数だけを受け取ります。(2) はget()で全レコードをモデルのCollectionとして取得したあと、PHP側のCollectionのcount()で数えています。結果の数値は同じでも、DBから取得するデータ量とメモリ使用量がまったく違います。
| 比較項目 | Query Builder / Eloquent の count() | Collection の count() |
|---|---|---|
| 数える場所 | データベース側 | PHP(アプリ)側 |
| 発行されるSQL | SELECT COUNT(*) | 全件取得のSELECT * |
| 取得データ量 | 件数のみ(軽い) | 全レコード(重い) |
| 向いている場面 | 件数だけ必要なとき | 取得済みデータを再利用するとき |
全件取得して数える場合とDB側で集計する場合のパフォーマンス差
件数だけが欲しいのにget()->count()とすると、全レコードをメモリに読み込んでから数えるため、データが多いほど無駄が大きくなります。一方、DB側のcount()はSELECT COUNT(*)を1回発行するだけで済み、転送量もメモリ使用量も最小限です。
// △ 件数だけ欲しいのに全件をメモリへ読み込んでいる
$count = Order::all()->count();
// ◎ DB側で集計するので軽い
$count = Order::count();使い分けの基本は「件数だけ必要ならDB側のcount()」「取得したデータを一覧表示などで再利用する予定があるなら、その取得済みCollectionに対してcount()」です。すでにget()したCollectionを表示に使いつつ件数も出す、といった場面ではCollectionのcount()が有効ですが、件数の取得だけを目的に全件取得するのは避けましょう。
配列・Collection・ページネーション結果での件数取得
件数の取り方はデータの形によって少しずつ異なります。代表的な3パターンを整理します。
// 配列: PHPの count() 関数を使う
$array = [1, 2, 3];
count($array); // 3
// Collection: count() メソッドを使う
collect($array)->count(); // 3
// ページネーション結果
$users = User::paginate(15);
$users->count(); // 今のページに含まれる件数(最大15)
$users->total(); // 全ページ合計の件数ページネーション結果で特に注意したいのがcount()とtotal()の違いです。paginate()の戻り値に対するcount()は「現在のページに表示されている件数」を返すのに対し、total()は「絞り込み条件に一致する全件数」を返します。「全部で何件」を出したいときはtotal()を使いましょう。
まとめ
Collectionの要素数を数えるときはcount()が基本で、条件付きならfilter()->count()、値ごとの集計ならcountBy()、有無の判定ならisEmpty() / isNotEmpty()と使い分けます。さらに、件数だけ必要なときは全件取得せずデータベース側のcount()を使うことで、無駄なメモリ消費とクエリ負荷を避けられます。要素の取り出しや加工とあわせて使う場面が多いので、pluckで必要な値を取り出す方法もあわせて押さえておくと、データ操作の幅が広がります。

コメントを残す