24.

PHP 配列からランダム値取得完全ガイド

編集
この記事の要点
  • 1 件取得: $arr[array_rand($arr)] または $arr[mt_rand(0, count($arr)-1)]
  • 複数件取得: array_rand($arr, 3) はキーの配列を返す (順序はそのまま)
  • シャッフル: shuffle($arr) は参照渡し (返り値は bool)
  • セキュア用途 (パスワード / トークン): random_int() / random_bytes()
  • 再現性 が欲しい場合は mt_srand(42) でシード固定

基本: 1 件ランダム取得

$fruits = ['apple', 'banana', 'cherry', 'date'];

// 方法 1: array_rand (キーを返す)
$key = array_rand($fruits);     // 例: 2
$item = $fruits[$key];           // 'cherry'

// 方法 2: mt_rand
$item = $fruits[mt_rand(0, count($fruits) - 1)];

// 方法 3: シャッフルして先頭
shuffle($fruits);
$item = $fruits[0];
// ※ 元配列を破壊するので注意。1 件だけなら array_rand が効率的

複数件ランダム取得

$fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];

// array_rand に第二引数で件数指定
$keys = array_rand($fruits, 3);   // [0, 2, 4] のようなキー配列
$picked = array_map(fn($k) => $fruits[$k], $keys);

// ★ 注意点
// 1. キーの順序は維持される (シャッフルされない)
// 2. 重複なし
// 3. 件数が配列より大きいと Warning + null

// 完全ランダム順 + 重複なし
shuffle($fruits);
$picked = array_slice($fruits, 0, 3);

// 重複ありの抽選
$picked = [];
for ($i = 0; $i < 3; $i++) {
    $picked[] = $fruits[array_rand($fruits)];
}

連想配列の場合

$prices = [
    'apple'  => 100,
    'banana' => 200,
    'cherry' => 300,
];

// キー (商品名) を取得
$key = array_rand($prices);     // 'banana'
$price = $prices[$key];

// 値からランダム選択
$values = array_values($prices);
$value = $values[array_rand($values)];

// キーと値の組
$key = array_rand($prices);
[$key, $value] = [$key, $prices[$key]];

シード設定 (再現性)

// シードを固定すると毎回同じ順序になる (テスト用に便利)
mt_srand(42);
echo mt_rand(1, 100);   // 例: 53 (常に同じ)
echo mt_rand(1, 100);   // 例: 17

// シャッフルも同様に固定
mt_srand(42);
$arr = [1, 2, 3, 4, 5];
shuffle($arr);
print_r($arr);   // 毎回同じ並び

// テスト後はシードをリセット (現在時刻ベース)
mt_srand();

重み付きランダム (Weighted Random)

// 出現確率を変えたい場合
$weighted = [
    'common'    => 70,    // 70%
    'rare'      => 25,    // 25%
    'legendary' => 5,     //  5%
];

function weightedRandom(array $weights): string {
    $total = array_sum($weights);
    $rand = mt_rand(1, $total);
    $cum = 0;
    foreach ($weights as $key => $w) {
        $cum += $w;
        if ($rand <= $cum) return $key;
    }
    return array_key_first($weights);
}

echo weightedRandom($weighted);   // 70% で 'common'

// 1000 回試行で分布確認
$result = [];
for ($i = 0; $i < 1000; $i++) {
    $r = weightedRandom($weighted);
    $result[$r] = ($result[$r] ?? 0) + 1;
}
print_r($result);   // [common => 約700, rare => 約250, legendary => 約50]

セキュア用途 (random_int / random_bytes)

// パスワードリセットトークンやセッション ID には mt_rand 禁止
// → 暗号学的に安全な random_int を使う (PHP 7+)

$secureKey = random_int(1, 1000);
$bytes = random_bytes(32);                    // 32 バイトのランダム
$token = bin2hex(random_bytes(32));           // 64 文字 hex
$base64 = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');

// パスワード生成
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$password = '';
for ($i = 0; $i < 16; $i++) {
    $password .= $chars[random_int(0, strlen($chars) - 1)];
}

// 配列からセキュアに 1 件取得
$item = $arr[random_int(0, count($arr) - 1)];

各関数の使い分け

関数速度暗号安全用途
rand()速いX非推奨 (古い)
mt_rand()速いXゲーム / 一般用途
random_int()やや遅Oトークン / セキュリティ
random_bytes()やや遅Oバイト列生成
openssl_random_pseudo_bytes()やや遅OOpenSSL 拡張必須

Laravel Collection の random()

$users = User::all();

// 1 件
$random = $users->random();

// 複数件
$picked = $users->random(3);   // Collection

// shuffle
$shuffled = $users->shuffle();

// クエリビルダで
$random = User::inRandomOrder()->first();    // ORDER BY RAND()
$randomMany = User::inRandomOrder()->limit(5)->get();

// ★ MySQL の ORDER BY RAND() は大きなテーブルで激重
// → 件数が多いなら範囲取得 + PHP 側でランダム選択を推奨
$ids = User::pluck('id');
$pickedIds = $ids->random(5);
$users = User::whereIn('id', $pickedIds)->get();

他言語との比較

// JavaScript
const arr = ['a', 'b', 'c'];
const item = arr[Math.floor(Math.random() * arr.length)];

// シャッフル (Fisher-Yates)
for (let i = arr.length - 1; i > 0; i--) {
  const j = Math.floor(Math.random() * (i + 1));
  [arr[i], arr[j]] = [arr[j], arr[i]];
}
# Python
import random
arr = ['a', 'b', 'c']

random.choice(arr)            # 1 件
random.sample(arr, 2)         # 重複なし複数
random.choices(arr, k=5)      # 重複あり複数
random.shuffle(arr)           # in-place

# 重み付き
random.choices(['a', 'b', 'c'], weights=[70, 25, 5], k=1)

# セキュア
import secrets
secrets.choice(arr)
secrets.token_hex(32)

FAQ

Q: array_rand($arr, 1)array_rand($arr) は同じ?
A: 違う。array_rand($arr) はスカラー (キー 1 個)、array_rand($arr, 1) は配列 (キー 1 個入り)。後者を使うとそのまま foreach で書ける。

Q: 抽選システムの正当性を確保したい
A: random_int() 使用 + 抽選ログを sealed (改ざん防止) で保存。さらに監査用にシード値を時刻ベースで記録するか、公開した hash をコミットメント方式で先に公開。

Q: 10 万件から 100 件ランダム取得したい
A: 全件取得は無駄。SELECT id FROM users で id だけ取り、PHP 側で array_rand($ids, 100)、その後 WHERE IN で本体取得が高速。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. インストール方法
  2. 文法
  3. Composerのインストール
  4. 内部関数
  5. フレームワーク
  6. エラー一覧
  7. 改行出力
  8. printとechoの違い
  9. シングルクォートとダブルクォートの違い
  10. returnとyieldの違い
  11. var_dumpをログ出力
  12. CSV読み込み
  13. 待機・処理の遅延
  14. ログファイルにエラーを出力する方法
  15. エラーログ出力関数
  16. URLパラメータの配列化
  17. empty, is_null. issetの判定比較表
  18. httpステータスコードの付与
  19. バージョンの確認
  20. php.ini
  21. APIを呼び出す方法
  22. 外部ファイルを呼び出す方法
  23. カンマ区切りの文字列を配列に変換
  24. 配列からランダムに値を取り出す方法
  25. Webスクレイピング

最近更新/作成されたページ