何のために「ランダム英数字文字列」を作るのか
まず、どんな場面で使うかをイメージしましょう。
ユーザーごとの招待コード
一時的なトークン(メール認証、パスワードリセット)
ファイル名やディレクトリ名の衝突回避用の識別子
こういうときに「ランダムな英数字の文字列」が欲しくなります。
ここで大事なのは、「なんとなくランダムっぽい」ではなく、
「推測されにくい」「偏りが少ない」ランダムさをきちんと確保することです。
絶対に押さえておきたいポイント:乱数は「暗号論的に安全なもの」を使う
mt_rand() や rand() を使ってはいけない場面
PHP には rand() や mt_rand() がありますが、
これらは「ゲームのサイコロ」レベルの乱数であって、
セキュリティ用途(トークン、招待コードなど)には向きません。
理由はシンプルで、「内部状態が推測されると、次の値が予測されうる」からです。
なので、
認証・認可・セキュリティに関わるランダム値
URL に載るトークン
ユーザーごとに一意であることが重要な識別子
こういった用途では、必ず「暗号論的に安全な乱数」を使います。
PHP でそれに該当するのが random_bytes() と random_int() です。
一番シンプルな実装:random_bytes() + 文字集合からの取り出し
文字集合を決める
まず、「どんな文字を使うか」を決めます。
よく使うのは「0–9, a–z, A–Z」の 62 文字です。
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
PHPこの中からランダムに文字を選んで、指定した長さ分つなげていきます。
実装例:任意長のランダム英数字文字列を生成する関数
/**
* ランダムな英数字文字列を生成する
*
* @param int $length 生成する文字列の長さ
* @return string
*/
function random_alnum_string(int $length): string
{
if ($length <= 0) {
throw new InvalidArgumentException('length must be positive');
}
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charsLength = strlen($chars);
$result = '';
// 必要な文字数分ループ
for ($i = 0; $i < $length; $i++) {
// 0〜$charsLength-1 の暗号論的に安全な乱数
$index = random_int(0, $charsLength - 1);
$result .= $chars[$index];
}
return $result;
}
PHP使い方の例です。
echo random_alnum_string(8); // 例: "a9F3kL0z"
echo random_alnum_string(32); // 例: "G7k2Pq9sL0xZ1mN8cD4vB6tY3wR5hU"
PHPここでの重要ポイントは、
「インデックスの取得に random_int() を使っている」ことです。
random_int() は内部的に暗号論的に安全な乱数ソースを使うので、
トークンや招待コードにも安心して使えます。
もう一つのパターン:random_bytes() から英数字にマッピングする
なぜ random_bytes() を使うパターンも知っておくと良いか
random_int() ベースの実装で十分ですが、
「バイト列として乱数を取り出して、それを文字にマッピングする」
というパターンもよく使われます。
これは、例えば「まず 16 バイトのランダム値を作って、それを 32 桁の 16 進文字列にする」ようなケースです。
$bytes = random_bytes(16);
$token = bin2hex($bytes); // 32 桁の 0-9a-f
PHPこれはこれで便利ですが、「英数字(0–9, a–z, A–Z)」に限定したい場合は、
さっきの random_int() パターンの方が素直です。
実務での使いどころのイメージ
パスワードリセット用トークン
例えば、パスワードリセット用の URL に載せるトークンを作るとします。
$token = random_alnum_string(64);
// DB に保存
// password_reset_tokens (user_id, token, expires_at, ...)
// ユーザーに送る URL
$url = 'https://example.com/reset-password?token=' . $token;
PHPここで mt_rand() などを使ってしまうと、
「トークンが推測される」リスクが一気に上がります。
random_alnum_string() の中で random_int() を使っていれば、
その心配はかなり小さくできます。
一時ファイル名・ディレクトリ名
一時ファイルや一時ディレクトリを作るときにも、
ランダムな英数字を足しておくと衝突しにくくなります。
$baseDir = '/tmp/myapp';
$dirName = 'session_' . random_alnum_string(16);
// /tmp/myapp/session_a9F3kL0zXy12AbCd みたいな感じ
$path = $baseDir . '/' . $dirName;
mkdir($path, 0700, true);
PHPここでは「セキュリティ」だけでなく、「一意性」も大事です。random_alnum_string() を使っておけば、
他のプロセスと名前がぶつかる可能性をかなり下げられます。
まとめ:今日からの「ランダム英数字文字列生成」ユーティリティ
押さえておきたいポイントは、次の 3 つです。
ランダム文字列をセキュリティ用途に使うなら、rand() や mt_rand() ではなく、必ず random_int() / random_bytes() を使う。
英数字だけのランダム文字列は、「文字集合を決めて、そのインデックスを random_int() で選ぶ」実装がシンプルで安全。
トークン、招待コード、一時ファイル名など、「推測されたら困る」「一意であってほしい」場面では、このユーティリティを必ず経由するようにする。
核になるコードは、これです。
function random_alnum_string(int $length): string
{
if ($length <= 0) {
throw new InvalidArgumentException('length must be positive');
}
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charsLength = strlen($chars);
$result = '';
for ($i = 0; $i < $length; $i++) {
$index = random_int(0, $charsLength - 1);
$result .= $chars[$index];
}
return $result;
}
PHPもし、あなたのコードの中で「mt_rand() をループして英数字を作っている」箇所があれば、そこがこの関数に置き換えるべきポイントです。
その一箇所を差し替えるだけで、アプリ全体の“ランダムの質”が一段上がります。

