訂單號需唯一、可追溯、長度適中、無規律可循(防刷單)。常見組成要素:時間、隨機數、業務前綴、校驗碼。
$yCode = ['A','B','C','D','E','F','G','H','I','J']; // 對應 2011-2020
$orderSn = $yCode[intval(date('Y')) - 2011]
. strtoupper(dechex(date('m'))) // 月份轉大寫十六進制
. date('d') // 日期
. substr(time(), -5) // 時間戳後 5 碼
. substr(microtime(), 2, 5) // 微秒部分
. sprintf('%02d', rand(0, 99)); // 兩位隨機數
// 輸出範例:A422694333616096
特點:含業務語義(年月日)、高並發下極低衝突率。
function build_order_no() {
return date('Ymd')
. substr(
implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))),
0, 8
);
}
echo build_order_no();
// 輸出範例:2014062356100485
原理:uniqid() 基於微秒時間,取後段字符轉 ASCII 碼再截取,變異度高。
function generateOrderNo(string $prefix = 'ORD'): string {
// 1. 日期時間(精確到毫秒)
$time = explode(' ', microtime());
$ms = sprintf('%03d', (int)($time[0] * 1000));
$date = date('YmdHis') . $ms; // 17 碼
// 2. 進程/執行緒 ID(PHP-FPM 可用 getmypid())
$pid = sprintf('%05d', getmypid() % 100000);
// 3. 遞增序號(Redis 原子計數或檔案鎖)
static $seq = 0;
$seq = ($seq + 1) % 10000;
$seqStr = sprintf('%04d', $seq);
// 4. 組合:前綴(3) + 時間(17) + PID(5) + 序號(4) = 29 碼
return $prefix . $date . $pid . $seqStr;
}
// 使用範例
echo generateOrderNo('ORD'); // ORD2024011512304512300001234
優點:
time() + rand(),高併發極易重複。Duplicate entry 異常重試。根據業務規模選擇適合策略:中小專案策略一/二足矣;高併發電商建議策略三或引入分布式 ID 生成服務。