首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP alphaID:數字 ID 轉短字母 ID 的經典演算法深度解析

     編輯:PHP 綜合知識

前言:YouTube 風格的短 ID 怎麼產生?

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

演算法核心原理

  1. 62 進位轉換:以 a-z 0-9 A-Z 為字母表,將整數反覆除以 62 取餘數,對應字元,最後反轉字串
  2. 雙向可逆:解碼時將字元還原為索引值,乘以 62位置 累加
  3. 填充機制:$padUp 透過加減 62^(n-1) 實現固定長度,避免短 ID 過短
  4. 密鑰打亂:以 SHA-256/512 雜湊對字母表排序,形成替換密碼表,非加密安全,僅阻擋肉眼推測

工程化應用建議

場景建議配置備註
內部系統 ID 混淆$padUp=6, $passKey=env('ALPHA_KEY')長度固定、輕度混淆
公開短網址/邀請碼$padUp=8, 無密鑰依賴 ID 空間大小防猜測,配合速率限制
分散式系統去中心化 ID不適用alphaID 需中央自增 ID,分散式請用 Snowflake/UUID
資料庫主鍵直接存字母 ID不建議主鍵宜用整數/二進位,字母 ID 只作展示層

效能與限制

  • 速度:單次轉換 ~0.5-1 微秒(PHP 8.x),極快
  • 最大支援:9007199254740992 (253,JS 安全整數上限),超過需 BCMath/GMP
  • 碰撞:純數學映射,**零碰撞**(單射函數)
  • 安全性:不可用於加密用途,密鑰僅增加逆向工程難度,已知明文可破解

現代替代方案

若需更高效能、標準化實作,推薦使用成熟套件:

  • tuupola/base62 (Composer) —— 純 PHP、支援大數、PSR 標準
  • hashids/hashids —— 可配置最小長度、字母表、鹽值,專為 ID 混淆設計
  • ramsey/uuid + Base62 —— 分散式場景首選
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved