短網址/短碼服務的核心是將任意長度字符串(如長 URL、用戶 ID)映射為定長、可逆或不可逆的短字符串。本文提供一個基於 SHA256 + Base62 變體的無狀態生成函數,無需數據庫存儲映射關係,適合分佈式系統。
<?php
/**
* 生成短碼/短鏈接標識
* @param string $input 原始字符串(長 URL、用戶 ID 等)
* @param int $minLen 最短碼長
* @param int $maxLen 最長碼長
* @return string 短碼
*/
function generateShortCode(string $input, int $minLen = 6, int $maxLen = 10): string {
// 自定義字符集:避免易混淆字符 (0/O, 1/l/I 等)
$charset = '1qaz2wsx3edc4rfv5tgb6yhn7ujm8ik9ol0p_';
$hash = hash('sha256', $input); // 64 hex chars
$step = random_int(8, 16); // 隨機步長增加熵
$segments = ceil(strlen($hash) / $step);
$code = '';
for ($i = 0; $i < $segments; $i++) {
$chunk = substr($hash, $i * $step, $step);
// hex -> int (取低 30 位)
$num = 0x3fffffff & (1 * '0x' . $chunk);
$idx = $num % strlen($charset);
$code .= $charset[$idx];
if (strlen($code) >= $maxLen) break;
}
return substr($code, 0, random_int($minLen, $maxLen));
}
// 測試
$urls = [
'https://example.com/very/long/url/with/many/parameters?foo=bar&baz=qux',
'user:123456',
'order:20240101:ABCDEF'
];
foreach ($urls as $u) {
echo "$u => " . generateShortCode($u) . PHP_EOL;
}
/* 輸出示例(每次運行結果不同)
https://example.com/... => 9k2m8p
user:123456 => q3wsx1
order:20240101:ABCDEF => 8ik9ol0p
*/
| 特性 | 說明 |
|---|---|
| 無狀態 | 無需數據庫存映射,同一輸入可重複生成(若固定 step/長度) |
| 低碰撞 | SHA256 256-bit 輸出,配合隨機 step/長度,極低碰撞概率 |
| 不可逆 | 單向雜湊,無法從短碼反推原始輸入 |
| 可定制字符集 | 排除易混淆字符,適合人工抄寫/口述場景 |