- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN:
Illuminate\Support\Collection::random - 関連: shuffle, take, first, sample
- 変更履歴: 既存メソッド(挙動の大きな変更なし)
要点(TL;DR)
- コレクションから ランダムに1件または複数件 を取得する
- 例:
$item = collect([1,2,3])->random(); - 罠:
- 件数指定が要素数超過だと 例外
- 1件取得時は Collectionではなく値 が返る
- LazyCollection非対応
概要
random() は、コレクション内の要素をランダムに取得するためのメソッドです。
UIのおすすめ表示、テストデータ抽出、サンプル取得など、順序に意味を持たせたくない場面で使います。
構文 / シグネチャ
random(int $number = null): mixed
引数
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
| $number | int | 任意 | null | 取得する件数 |
- 戻り値
$number未指定: 要素そのもの(mixed)$number指定: Collection
- 例外/副作用
- 要素数 <
$numberの場合InvalidArgumentException
- 要素数 <
使用例
最小例
use Illuminate\Support\Collection;
$col = collect(['apple', 'banana', 'orange']);
$item = $col->random(); // string
複数件取得
$items = $col->random(2); // Collection
実務例(おすすめ記事を3件表示)
use App\Models\Post;
$posts = Post::query()
->where('published', true)
->get()
->random(3);
inRandomOrder()との使い分け(DB側でランダム抽出したい場合)
Collection::random() は、すでにメモリ上にあるコレクションからランダムに取り出すメソッドです。一方、Eloquentのクエリビルダには inRandomOrder() という別のメソッドがあり、DB側でランダムに並び替えてから取得できます。件数の多いテーブルから1〜数件だけ欲しい場合は、全件を get() してから random() するより inRandomOrder() の方が効率的です。
use App\Models\Post;
// 非効率: 全件をメモリに読み込んでからランダム抽出
$post = Post::all()->random();
// 効率的: DB側でランダムに並び替えて1件だけ取得
$post = Post::inRandomOrder()->first();
// 複数件(DB側でランダム抽出)
$posts = Post::inRandomOrder()->limit(3)->get();
| 方法 | 処理される場所 | 向いているケース |
|---|---|---|
Collection::random() | PHP(メモリ上) | 既に取得済みの配列・コレクションから抽出したい |
Query::inRandomOrder() | DB(SQLのORDER BY RAND()相当) | 大きいテーブルから直接1〜数件だけ欲しい |
ただし inRandomOrder() はテーブル件数が多いと ORDER BY RAND() のコストが無視できなくなるため、大規模テーブルでは注意が必要です。
よくある落とし穴・注意
- 戻り値の型に注意
$col->random(); // 値 $col->random(1); // Collection - 件数超過は例外
collect([1,2])->random(3); // 例外 - 空のコレクションでも例外
collect([])->random(); // InvalidArgumentException
事前に isEmpty で件数を確認するか、try/catchで握りつぶさず空配列時の分岐を用意する random(0)は例外にならないcollect([1,2,3])->random(0); // 空のCollection
件数0は「0件取得」として扱われ、要素数超過の例外にはならない(0とnullの挙動の違いに注意)- LazyCollectionでは使えない
- 必要なら
->collect()->random()に変換
- 必要なら
ランダムな文字列生成(Str::random)と混同しない
「laravel random」で検索すると、コレクションからの要素抽出ではなくランダムな文字列(トークンやパスワード)を生成したい場合にたどり着くこともあります。本記事のCollection::random()とは別物なので、目的に応じて使い分けてください。
| 目的 | 使うもの | 例 |
|---|---|---|
| コレクションから要素をランダム抽出 | Collection::random()(本記事) | collect([1,2,3])->random() |
| ランダムな文字列(トークン等)を生成 | Illuminate\Support\Str::random() | Str::random(32) // 32文字のランダム文字列 |
代替・関連APIとの比較
| メソッド | 特徴 | 選定基準 |
|---|---|---|
| random | 完全ランダム | 単発・抽出 |
| shuffle | 全体をシャッフル | 並び替えたい |
| take | 先頭から取得 | 順序重視 |
| sample | 統計的サンプリング | 大量データ |
テスト例(Pest)
it('returns random item', function () {
$col = collect([1, 2, 3]);
$item = $col->random();
expect($col)->toContain($item);
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| InvalidArgumentException | 件数超過 | 件数を制限 |
| 型エラー | 1件取得で値が返る | (array) や random(1)->first() |
よくある質問(FAQ)
Q. テストでrandom()の結果を固定(再現)したい場合は?
A. random() 自体にシード値を指定するオプションはありません。テストで結果を固定したい場合は、random() を使わずに要素数1件のコレクションに対して呼び出すか、対象を明示的に指定してアサーションする(「返り値がコレクションに含まれているか」を検証する)方法が確実です。上記のPestの例のように toContain() で検証するのが定番です。
Q. 重複なしで複数件をランダムに取得したい場合は?
A. random($number) で複数件を指定すると、コレクション内で重複しない $number 件がランダムに返されます(同じ要素が2回選ばれることはありません)。重複ありで抽選したい場合は random() をループで複数回呼び出す必要があります。
Q. EloquentモデルをDB側でランダムに1件取得するには?
A. Model::inRandomOrder()->first() を使います。Collection::random() はメモリ上のコレクションが対象のため、全件取得してから絞り込むより inRandomOrder() でDB側にランダム抽出させる方が効率的です。詳細は本記事の「inRandomOrder()との使い分け」を参照してください。
関連記事
- 初心者向けガイド: Laravel Collectionの基本と使い方をマスターしよう
- find — Eloquent Collectionから主キーで検索する方法
- contains — コレクションに値/条件が含まれるか判定する
参考リンク
- Laravel公式ドキュメント(Collections / random)
https://laravel.com/docs/collections#method-random
