なぜ進数変換が重要なのか
Webアプリケーション開発において、データベースの自動採番ID(プライマリキー)をそのままURLに露出させることは、セキュリティや設計の観点から推奨されない場合があります。また、単純な連番(1, 2, 3…)をそのままURLに使うと、桁数がすぐに増えてしまい、視認性が悪くなります。
このような課題を解決するのが「n進数変換」です。特に、0-9、a-z、A-Zの計62文字を利用する「62進数」を使えば、非常に短い文字列で大きな数値を表現できます。これにより、短縮URLの生成や、推測困難なID管理を効率的に実現できます。
基礎知識:基数変換の仕組み
私たちが普段使っている「10進数」は0-9の10個の記号を使いますが、n進数は「n個」の記号を使って数値を表現します。
62進数の場合、0-9(10文字)+ a-z(26文字)+ A-Z(26文字)の計62文字をマッピングします。
例えば、10進数の「1000」を62進数に変換すると「g8」となります。これだけで、URLの長さを劇的に短縮できることが分かります。
実装:62進数変換アルゴリズム
PHPでこの仕組みを実装するには、数学的な剰余演算(fmod)と除算(floor)を用います。以下に、汎用性の高いエンコード・デコード関数を提示します。
サンプルプログラム
/
function encode62($number, $chars = ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’) {
$result = “”;
$base = strlen($chars);
// 0の場合は特殊処理
if ($number == 0) return $chars[0];
while ($number > 0) {
// 剰余を求めて、対応する文字を先頭に追加
$result = $chars[fmod($number, $base)] . $result;
// 整数除算で桁を繰り下げる
$number = floor($number / $base);
}
return $result;
}
/
- 62進数文字列を数値へ変換(デコード)
/
function decode62($str, $chars = ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’) {
$result = 0;
$base = strlen($chars);
$table = array_flip(str_split($chars));
$digits = array_reverse(str_split($str));
foreach ($digits as $i => $char) {
if (!isset($table[$char])) return false;
// 各桁の値を基数の累乗で加算
$result += pow($base, $i) $table[$char];
}
return $result;
}
// 使用例
$id = 123456789;
$encoded = encode62($id);
echo “元のID: {$id} -> 変換後: {$encoded}” . PHP_EOL;
echo “デコード結果: ” . decode62($encoded) . PHP_EOL;
?>
応用・注意点
1. 文字の順序によるソート順
上記実装では、`0-9`, `a-z`, `A-Z` の順で定義していますが、この並び順を変えると「変換後の文字列」の順序も変わります。もし変換後の文字列をデータベースでソートしたい場合は、文字の定義順を考慮する必要があります。
2. Base64との違い
参考本文にもある通り、Base64は「+」や「/」を含みます。これらはURLエンコードが必要になる文字であるため、URLとしてそのまま使う短縮IDの生成には、今回のような「英数字のみ」の62進数変換がより適しています。
3. バリデーション
デコード時に、許可されていない文字(記号など)が混入していないかチェックする処理を入れることで、外部からの不正な入力に対する堅牢性を高めることができます。
この仕組みを導入することで、URLの短縮だけでなく、IDの難読化にも役立ちます。ぜひ実務のコードに取り入れてみてください。