「短縮 ID 生成」で何をしたいのかイメージする
まず、どんな場面で「短い ID」が欲しくなるかをイメージしてみましょう。
URL 短縮サービスの「短いコード」
人に読み上げやすい予約番号や受付番号
画面上に表示する「問い合わせ ID」
こういうときに、UUID のような長い文字列ではなく、
a9F3kL0zXy12AbCd
といった「そこそこ一意で、そこそこ短い ID」が欲しくなります。
ここで大事なのは、「短くした瞬間に、完全な一意性は捨てている」という感覚です。
つまり、UUID ほどの“絶対ぶつからない感”はない代わりに、「実務上ほぼ困らない程度の衝突確率」で割り切る、という設計になります。
短縮 ID を設計するときに考えること
どのくらいの長さにするか
長さが短いほど、衝突(同じ ID が二度出る)の確率は上がります。
例えば、英数字 62 種類を使うとします。
長さ 6 文字だと、62^6 ≒ 56 億通り
長さ 8 文字だと、62^8 ≒ 2.18 兆通り
「何件くらいのデータに対して使うのか」「衝突したらどう扱うのか」を考えながら、長さを決めます。
業務でよくあるのは、8〜12 文字くらいです。
どんな文字を使うか
URL に載せることが多いなら、英数字だけにしておくと扱いやすいです。
ここでは、次の 62 文字を使う前提で進めます。
0-9a-zA-Z
これで「短くて、URL にも載せやすい ID」が作れます。
コアとなる考え方:ランダム英数字列を「短縮 ID」として使う
短縮 ID の一番シンプルな作り方は、「ランダムな英数字列をそのまま ID として使う」ことです。
やることは三つだけです。
- 使う文字集合を決める(英数字 62 文字など)
- その中からランダムに文字を選んで、指定した長さ分つなげる
- 乱数には必ず
random_int()を使う
ここで random_int() を使うのが重要です。mt_rand() などではなく、暗号論的に安全な乱数を使うことで、「推測されにくい ID」になります。
実装:短縮 ID 生成ユーティリティ
シンプルな短縮 ID 生成関数
まずは、英数字だけを使った短縮 ID 生成関数を作ります。
/**
* 短縮 ID を生成する(英数字のみ)
*
* @param int $length 生成する ID の長さ
* @return string
*/
function generate_short_id(int $length = 8): 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 generate_short_id(); // デフォルト8文字 例: "a9F3kL0z"
echo generate_short_id(10); // 10文字 例: "Xy12AbCdE3"
echo generate_short_id(12); // 12文字 例: "G7k2Pq9sL0xZ"
PHPここでの重要ポイントは、「長さを引数で変えられるようにしておく」ことです。
用途によって「6文字でいい」「いや 12 文字欲しい」と変わるので、ユーティリティとして柔軟にしておくと再利用しやすくなります。
UUID v4 を「短縮 ID」に変換する、という発想もある
UUID をそのまま使うのは長い、でも一意性は欲しい
すでにシステムの中で UUID v4 を使っている場合、
「内部では UUID、外に見せるのは短縮 ID」という設計もよくあります。
このときの発想はこうです。
- 内部 ID として UUID v4 を生成する
- UUID を 16進数として扱い、それを 62 進(英数字)に変換する
- その結果の一部、または全部を「短縮 ID」として使う
ここまでやると少し実装が重くなるので、初心者向けには「ランダム英数字列をそのまま短縮 ID として使う」方が分かりやすいです。
ただ、「内部 ID と外部 ID を分ける」という考え方自体は、実務ではかなりよく出てきます。
実務での使いどころのイメージ
URL 短縮サービス風のコード
例えば、URL 短縮サービスのようなものを作るとします。
$originalUrl = 'https://example.com/very/long/url/...';
$shortId = generate_short_id(8);
// DB に保存
$stmt = $pdo->prepare('INSERT INTO short_urls (short_id, url) VALUES (:short_id, :url)');
$stmt->execute([
':short_id' => $shortId,
':url' => $originalUrl,
]);
$shortUrl = 'https://s.example.com/' . $shortId;
// ユーザーにはこの短い URL を見せる
PHPアクセス時は、/a9F3kL0z のようなパスを受け取って、short_urls テーブルから元の URL を引き当ててリダイレクトします。
問い合わせ番号や受付番号
問い合わせフォームで送信された内容に対して、
ユーザーに「問い合わせ番号」を返したい場面を考えてみます。
$ticketId = generate_short_id(10);
$stmt = $pdo->prepare('INSERT INTO tickets (ticket_id, user_id, subject, body) VALUES (:ticket_id, :user_id, :subject, :body)');
$stmt->execute([
':ticket_id' => $ticketId,
':user_id' => $userId,
':subject' => $subject,
':body' => $body,
]);
echo 'お問い合わせ番号: ' . $ticketId;
PHPユーザーはサポートに連絡するときに、この短縮 ID を伝えれば、
オペレーター側は tickets テーブルからすぐに該当データを探せます。
衝突(同じ ID が出る)とどう付き合うか
短縮 ID は、UUID ほどの一意性はありません。
理論上は、同じ ID が二度生成される可能性があります。
実務では、次のような対策を組み合わせます。
ID を保存するときに「ユニーク制約」を張っておく(UNIQUE インデックス)。
もし INSERT 時にユニーク制約エラーが出たら、「もう一度 ID を生成し直す」。
コードのイメージはこうです。
function create_unique_short_id(PDO $pdo, int $length = 8): string
{
while (true) {
$id = generate_short_id($length);
try {
$stmt = $pdo->prepare('INSERT INTO something (short_id) VALUES (:id)');
$stmt->execute([':id' => $id]);
return $id;
} catch (PDOException $e) {
// ユニーク制約違反なら再トライ(エラーコードは環境に応じて判定)
// それ以外のエラーなら投げ直す
}
}
}
PHPこうしておけば、「衝突したらやり直す」という形で、
短縮 ID の“弱点”を現実的にカバーできます。
まとめ:今日からの「短縮 ID 生成」ユーティリティ
ポイントを整理すると、こうなります。
短縮 ID は、「完全な一意性」ではなく「実務上ほぼ困らない一意性」と「短さ」のトレードオフ。
英数字 62 文字から random_int() でランダムに選んで並べるのが、シンプルで安全な実装。
衝突の可能性はゼロではないので、DB のユニーク制約と「衝突したら再生成」の仕組みをセットで考える。
核になる関数は、これです。
function generate_short_id(int $length = 8): 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() を使って短いコードを作っている」箇所があれば、そこがこのユーティリティに差し替えるべきポイントです。
その一箇所を置き換えるだけで、「短くて、推測されにくくて、実務で使いやすい ID」が手に入ります。
