| 方案 | 長度 | 有序性 | 碰撞機率 | 可預測性 | 適用場景 |
|---|---|---|---|---|---|
| UUID v4 (Random) | 36 字元 | 無 | 極低 (122-bit 隨機) | 不可預測 | 通用唯一 ID、主鍵 |
| UUID v7 (Time-ordered) | 36 字元 | 毫秒級有序 | 極低 | 部分可預測 (時間) | 資料庫主鍵、索引友善 |
| ULID | 26 字元 | 毫秒級有序 | 極低 (128-bit) | 部分可預測 | URL 友善、主鍵、日誌排序 |
| nanoid | 21 字元 (可調) | 無 | 可調 (預設 ~149-bit) | 不可預測 | 短 ID、URL 友善、前端生成 |
| SHA-256 雜湊 | 64 字元 | 無 | 極低 | 確定性 (同輸入同輸出) | 內容定址、去重、驗證 |
| random_bytes + base64 | 可調 | 無 | 可調 | 不可預測 | 高安全 Token、加密金鑰 |
| 時間戳+隨機數 (原文做法) | 40 字元 (SHA1) | 秒級有序 | 中 (依賴隨機源品質) | 部分可預測 | 簡單場景、舊系統相容 |
<?php
// 使用 ramsey/uuid (Composer: composer require ramsey/uuid)
use Ramsey\Uuid\Uuid;
$id = Uuid::uuid4()->toString(); // "550e8400-e29b-41d4-a716-446655440000"
// 原生實作 (RFC 4122 v4)
function uuidV4(): string
{
$bytes = random_bytes(16);
// 設定版本位元 (4) 與變體位元 (10x)
$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x40); // version 4
$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80); // variant 10x
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}
<?php
// ULID 實作 (Crockford's Base32, 26 chars)
function ulid(): string
{
$ms = (int)(microtime(true) * 1000);
$time = str_pad(base_convert($ms, 10, 32), 10, '0', STR_PAD_LEFT); // 10 chars
$rand = '';
$bytes = random_bytes(10); // 80 bits
foreach (str_split(bin2hex($bytes), 2) as $b) {
$rand .= '0123456789ABCDEFGHJKMNPQRSTVWXYZ'[hexdec($b) & 0x1F];
}
return $time . $rand; // 26 chars, e.g. 01ARZ3NDEKTSV4RRFFQ69G5FAV
}
// UUID v7 (RFC 9562 草案,時間前 48 bits + 版本 7 + 亂數)
function uuidV7(): string
{
$ms = (int)(microtime(true) * 1000);
$timeBytes = pack('J', $ms); // 6 bytes (48 bits), big-endian
$randBytes = random_bytes(10);
$bytes = substr($timeBytes, 2) . $randBytes; // 16 bytes
$bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x70); // version 7
$bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80); // variant
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($bytes), 4));
}
<?php
function secureToken(int $bytes = 32): string
{
// URL-safe Base64, 無填充
return rtrim(strtr(base64_encode(random_bytes($bytes)), '+/', '-_'), '=');
}
// 使用
$apiKey = 'sk_' . secureToken(24); // sk_xxxxx... (43 chars)
$csrf = secureToken(32); // 43 chars
$reset = secureToken(16); // 22 chars
<?php
function contentHash(string $data, string $algo = 'sha256'): string
{
return hash($algo, $data);
}
// 檔案雜湊 (串流處理大檔案)
function fileHash(string $path, string $algo = 'sha256'): string
{
return hash_file($algo, $path);
}
BIGINT AUTO_INCREMENT 最簡單高效。sha1(time().rand()) — 熵來源弱、長度固定 40 字元、無序、SHA1 已棄用。random_bytes() / random_int() (PHP 7+ CSPRNG),禁用 rand()、mt_rand()、uniqid()、md5(time()) 產生安全 Token。hash_equals() 恆時比較。hash('sha256', $token),驗證時比對雜湊。uuidV4 (ramsey) : ~0.45 秒
uuidV4 (native) : ~0.18 秒
ulid() : ~0.12 秒
uuidV7() : ~0.15 秒
secureToken(32) : ~0.10 秒
sha1(time().rand()) : ~0.08 秒 (但不安全!)
random_bytes(16) : ~0.06 秒 (最基礎操作)
PHP 產生唯一 ID 已進入標準化、高效能、安全優先新時代。核心建議:
棄用 sha1(time().rand()) 等弱熵、定長、無序舊寫法。引入 ramsey/uuid、ulid/php-ulid、hidehalo/nanoid-php 等成熟套件,專注業務邏輯而非重造輪子。