YouTube 影片網址 youtube.com/watch?v=yzNjIBEdyww 中的 v= 參數就是將資料庫自增 ID 透過 alphaID 演算法轉為 62 進位字串。本文深度解析 Kevin van Zonneveld 經典實作的原理、特性與工程化應用。
<?php
/**
* 將數字 ID 雙向轉換為短字母數字 ID
*
* @param mixed $in 整數 ID 或字母 ID 字串
* @param bool $toNum true: 字母→數字;false: 數字→字母
* @param mixed $padUp 整數: 最小長度填充;false: 不填充
* @param string $passKey 可選密鑰,打亂字母表增加逆向難度
* @return mixed 整數或字串
*/
function alphaID($in, $toNum = false, $padUp = false, $passKey = null) {
$index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$base = strlen($index); // 62
// 可選:密鑰打亂字母表(非加密級,僅增加逆向工程難度)
if ($passKey !== null) {
$chars = str_split($index);
$hash = hash('sha256', $passKey);
$hash = (strlen($hash) < $base) ? hash('sha512', $passKey) : $hash;
$pairs = array_combine(str_split($hash), $chars);
krsort($pairs); // 依 hash 降序排序
$index = implode('', $pairs);
}
if ($toNum) {
// 字母 ID → 數字 ID
$in = strrev($in);
$out = 0;
$len = strlen($in) - 1;
for ($t = 0; $t <= $len; $t++) {
$bcp = function_exists('bcpow') ? bcpow($base, $len - $t) : pow($base, $len - $t);
$out += strpos($index, $in[$t]) * $bcp;
}
// 處理填充邏輯
if (is_numeric($padUp) && $padUp > 0) {
$out -= pow($base, $padUp - 1);
}
return (string)$out; // 可能超出 PHP_INT_MAX,回傳字串
} else {
// 數字 ID → 字母 ID
if (is_numeric($padUp) && $padUp > 0) {
$in += pow($base, $padUp - 1);
}
$out = '';
for ($t = (function_exists('log') ? floor(log($in, $base)) : (int)(log($in) / log($base))); $t >= 0; $t--) {
$bcp = function_exists('bcpow') ? bcpow($base, $t) : pow($base, $t);
$a = (int)(($in / $bcp) % $base);
$out .= $index[$a];
$in -= $a * $bcp;
}
return strrev($out);
}
}
<?php
// 基本雙向轉換
$id = 1234567890;
$code = alphaID($id); // 'PpQXn7COf'
$back = alphaID($code, true); // '1234567890'
echo "$id → $code → $back\n";
// 指定最小長度 6(自動填充)
$code6 = alphaID(123, false, 6); // '00002Z' (視字母表而定)
echo "Padded: $code6\n";
// 加入密鑰(同一密鑰下雙向可逆,不同密鑰結果完全不同)
$codeKey = alphaID($id, false, false, 'my_secret_key');
$backKey = alphaID($codeKey, true, false, 'my_secret_key');
echo "With key: $codeKey → $backKey\n";
// 大數字測試(需 BCMath)
echo "Max 64-bit: " . alphaID('9223372036854775807') . "\n"; // 可處理 2^63-1
a-z 0-9 A-Z 為字母表,將整數反覆除以 62 取餘數,對應字元,最後反轉字串$padUp 透過加減 62^(n-1) 實現固定長度,避免短 ID 過短| 場景 | 建議配置 | 備註 |
|---|---|---|
| 內部系統 ID 混淆 | $padUp=6, $passKey=env('ALPHA_KEY') | 長度固定、輕度混淆 |
| 公開短網址/邀請碼 | $padUp=8, 無密鑰 | 依賴 ID 空間大小防猜測,配合速率限制 |
| 分散式系統去中心化 ID | 不適用 | alphaID 需中央自增 ID,分散式請用 Snowflake/UUID |
| 資料庫主鍵直接存字母 ID | 不建議 | 主鍵宜用整數/二進位,字母 ID 只作展示層 |
9007199254740992 (253,JS 安全整數上限),超過需 BCMath/GMP若需更高效能、標準化實作,推薦使用成熟套件:
tuupola/base62 (Composer) —— 純 PHP、支援大數、PSR 標準hashids/hashids —— 可配置最小長度、字母表、鹽值,專為 ID 混淆設計ramsey/uuid + Base62 —— 分散式場景首選