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

PHP uniqid() 生成唯一 ID 完整指南:原理、用法與進階方案

     編輯:PHP 綜合知識

uniqid() 基於微秒時間生成唯一標識,廣泛用於臨時文件名、緩存鍵、安全 Token、數據庫主鍵等場景。本文系統講解函數原型、基礎用法、與 md5() 組合、可排序性優勢,並對比三種生成 UUID 的進階方案。

函數原型與版本

string uniqid([string $prefix = ""][, bool $more_entropy = false])
// PHP 3, 4, 5, 7, 8 全版本可用
  • $prefix:前綴,區分業務場景(如 order_, token_)。
  • $more_entropy:true 時在末尾增加額外熵(組合線性同餘產生器),長度達 23 字符,碰撞概率更低。

基礎用法實例

<?php
// 1. 默認 13 字符(十六進制微秒時間)
echo uniqid();        // 例: 65a8f3c2d1e4b

// 2. 帶前綴
echo uniqid('ord_');  // ord_65a8f3c2d1e4b

// 3. 更多熵(23 字符)
echo uniqid('', true); // 65a8f3c2d1e4b7.12345678

// 4. 結合 md5() 產生 32 字符定長 ID
echo md5(uniqid('', true)); // dfbc5c8c6438de075da28b3c8a413fd0

// 5. 連續生成展示可排序性
echo uniqid() . "\n"; // 65a8f3c2d1e4b
echo uniqid() . "\n"; // 65a8f3c2d1e5a
echo uniqid() . "\n"; // 65a8f3c2d1e6c
// 按字典序排序即為時間順序,利於數據庫索引/分頁

核心優勢:可排序性

因基於時間戳,uniqid() 生成的 ID 天然按生成順序排序。對比 UUID v4(隨機)或 md5(rand()),在數據庫聚簇索引(InnoDB 主鍵)場景下,順序寫入大幅減少頁分裂,寫入性能提升 30%+。

三種生成 UUID 進階方案對比

方案一:md5(time() . mt_rand()) — 簡單但有極低碰撞風險

$id = md5(time() . mt_rand(1, 1000000));
// 秒級時間 + 隨機數,高併發下理論可能重複

方案二:自定義 UUID v4 風格(基於 uniqid + 隨機)

function uuid() {
    if (function_exists('com_create_guid')) { // Windows COM
        return com_create_guid();
    }
    mt_srand((double)microtime() * 10000); // PHP < 4.2.0 需要
    $charid = strtoupper(md5(uniqid(rand(), true)));
    $hyphen = '-';
    return '' // '{'
        . substr($charid, 0, 8) . $hyphen
        . substr($charid, 8, 4) . $hyphen
        . substr($charid, 12, 4) . $hyphen
        . substr($charid, 16, 4) . $hyphen
        . substr($charid, 20, 12); // '}'
}
// 輸出格式: 5DDB650F-4389-F4A9-A100-501EF1348872

方案三:RFC 4122 風格(引入請求上下文熵)

public function create_guid($namespace = '') {
    static $guid = '';
    $uid = uniqid("", true);
    $data = $namespace
        . $_SERVER['REQUEST_TIME']
        . $_SERVER['HTTP_USER_AGENT']
        . $_SERVER['LOCAL_ADDR']
        . $_SERVER['LOCAL_PORT']
        . $_SERVER['REMOTE_ADDR']
        . $_SERVER['REMOTE_PORT'];
    $hash = strtoupper(hash('ripemd128', $uid . $guid . md5($data)));
    $guid = '{'
        . substr($hash, 0, 8) . '-'
        . substr($hash, 8, 4) . '-'
        . substr($hash, 12, 4) . '-'
        . substr($hash, 16, 4) . '-'
        . substr($hash, 20, 12)
        . '}';
    return $guid;
}
// 輸出: {E2DFFFB3-571E-6CFC-4B5C-9FEDAAF2EFD7}

方案選型建議

場景推薦方案理由
臨時文件/緩存鍵/短期 Tokenuniqid('prefix_', true)極快、長度適中、可排序、無依賴
數據庫主鍵/分布式 ID(單機/低併發)md5(uniqid('', true))32 字符定長、可排序、碰撞極低
分布式系統/高併發/跨語言互通UUID v7 (時間有序) / Snowflake / ULID標準化、強排序、無中心協調
Windows 環境需符合 COM 規範com_create_guid()原生實現,格式標準

現代替代方案:PHP 8.2+ Random Extension

<?php
// PHP 8.2+ 推薦:密碼學安全隨機 UUID v4
$uuid = \Random\Randomizer::getBytes(16);
$uuid[6] = ($uuid[6] & 0x0f) | 0x40; // version 4
$uuid[8] = ($uuid[8] & 0x3f) | 0x80; // variant 10
echo bin2hex($uuid); // 32 字符十六進制
// 或使用 symfony/uid, ramsey/uuid 等成熟庫

避坑指南

  • 不要用於加密用途: uniqid() 可預測(基於時間),安全 Token 必須用 random_bytes() / openssl_random_pseudo_bytes()。
  • 高併發微秒級碰撞: 同一微秒內多次調用可能重複,開啟 $more_entropy=true 或組合 random_int()。
  • 數據庫主鍵長度: CHAR(32) 存 md5(uniqid()),或 CHAR(36) 存標準 UUID,避免 VARCHAR 索引效率較低。

理解 uniqid() 的時間有序特性與局限性,結合業務場景選擇最適合的唯一 ID 生成策略,是 PHP 開發者處理分布式標識的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved