You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel如何生成1000个唯一下载码并确保总数达标?

Laravel生成唯一6位下载码的优化实现

问题背景

我需要向数据库填充1000个唯一的6位下载码,目前在Laravel控制器中编写了生成代码,但未校验生成的码是否唯一。现有代码能计算需生成的数量并生成6位码保存,但存在重复风险,我自己写了一个校验逻辑,想找更优的实现方式。

现有控制器代码

// 计算已生成的下载码数量
$totalcount_generated_so_far = DownloadCode::count();
$quantity = 1000 - $totalcount_generated_so_far;

if($quantity < 0) {
    return "无需生成!已有超过1000个下载码。";
}

$object = new DownloadCode;
for($i = 0; $i < $quantity; $i++) {    
    $object = new DownloadCode;

    $length = 6;
    $keys = array_merge(range(1,9), range('A', 'Z'));

    $key1 = "";
    // 注意:此处循环变量和外层for的$i重名,会导致逻辑错误
    for($i=0; $i < $length; $i++) {
        $key1 .= $keys[mt_rand(0, count($keys) - 1)];
    }
    $object->code_download = $key1;  // 生成的6位码

    $object->save(); 
}
return $quantity . " 个下载码已生成。";

我的初步校验方案

// 校验唯一性
$uniq_test = DownloadCode::where('code_download',$key2)->first(); 
if($uniq_test) {
    $i--; // 重复则减少循环计数,重新生成
} else {
    $object->save(); 
}

这个方案存在几个问题:

  • 每次生成后都要查询数据库,批量生成时效率低下
  • 循环变量$i重名会导致逻辑混乱
  • 无法处理并发场景:如果多个请求同时生成相同的码,都通过了查询校验后插入,仍然会出现重复数据

更优实现方式

方案1:数据库唯一约束+异常捕获(推荐,保证绝对唯一)

首先给code_download字段添加唯一索引,从数据库层面阻止重复数据:

在迁移文件中修改字段定义:

Schema::create('download_codes', function (Blueprint $table) {
    // 其他字段...
    $table->string('code_download')->unique();
});

然后修改控制器代码,利用异常捕获处理重复情况:

// 计算需生成的数量
$existingCount = DownloadCode::count();
$quantity = 1000 - $existingCount;

if ($quantity <= 0) {
    return "无需生成!已有超过1000个下载码。";
}

$length = 6;
$keys = array_merge(range(1, 9), range('A', 'Z'));
$generated = 0;

while ($generated < $quantity) {
    $code = '';
    // 修正循环变量名,避免和外层冲突
    for ($j = 0; $j < $length; $j++) {
        $code .= $keys[mt_rand(0, count($keys) - 1)];
    }

    try {
        DownloadCode::create(['code_download' => $code]);
        $generated++;
    } catch (\Illuminate\Database\QueryException $e) {
        // 捕获唯一约束冲突异常,跳过重复码,继续生成
        continue;
    }
}

return "已成功生成 {$quantity} 个唯一下载码。";

优点:数据库层面保证唯一性,即使并发请求也不会出现重复;代码逻辑简洁,无需提前查询所有现有码。


方案2:批量生成+内存去重(高效批量生成)

先查询所有已存在的码,在内存中过滤重复值,批量生成足够数量的唯一码后再插入数据库,减少数据库交互次数:

// 计算需生成的数量
$existingCount = DownloadCode::count();
$quantity = 1000 - $existingCount;

if ($quantity <= 0) {
    return "无需生成!已有超过1000个下载码。";
}

$length = 6;
$keys = array_merge(range(1, 9), range('A', 'Z'));
// 获取所有已存在的下载码
$existingCodes = DownloadCode::pluck('code_download')->toArray();
$newCodes = [];

while (count($newCodes) < $quantity) {
    $code = '';
    for ($j = 0; $j < $length; $j++) {
        $code .= $keys[mt_rand(0, count($keys) - 1)];
    }

    // 检查是否已存在(包括已生成的新码)
    if (!in_array($code, $existingCodes) && !in_array($code, $newCodes)) {
        $newCodes[] = $code;
    }
}

// 批量插入数据库
DownloadCode::insert(
    collect($newCodes)->map(fn($code) => ['code_download' => $code])->toArray()
);

return "已成功生成 {$quantity} 个唯一下载码。";

优点:减少数据库查询次数,批量插入效率更高;适合一次性生成大量码的场景。


内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:09:27