Advertisement

【交流】PHP生成唯一邀请码

阅读量:

目录

前言:

1.随机生成,核对user表是否已存在

代码:

解析:

缺点:

2.建表建库,每次从表中随机抽取一条,用完时扩充

表结构

表视图

代码

解析

缺点

结论:


前言:


目前使用了两种生成唯一邀请码的方法,都觉的不是很完美,有什么好的方法大姐可以交流一下,以下是我的代码逻辑:

1.随机生成,核对user表是否已存在


代码:
复制代码
 function generateInvitationCode($i = 1)

    
 { 
    
     $start = 10000;
    
     $end = 99999;
    
  
    
     // 如果循环了n次,仍然重复,则扩充范围
    
     // 以避免10000-99999的数字全部都被占用了,在成无限循环
    
     $multiple = bcdiv($i, 50);
    
     if($multiple >= 1) {
    
     $start = $start . str_repeat(0, $multiple); // 拼接$multiple个0
    
     $end = $end . str_repeat(9, $multiple); // 拼接$multiple个9
    
     }
    
  
    
     // 生成随机数
    
     $invitationCode = rand($start, $end); 
    
  
    
     // 检查邀请码是否已经存在于数据库中
    
     while (checkInvitationCodeExists($invitationCode)) {
    
     // 如果邀请码已经存在,则重新生成
    
     $invitationCode = generateInvitationCode($i + 1);
    
     }
    
  
    
     return $invitationCode;
    
 }
    
 /** * 检查不否已存邀请码
    
 */
    
 function checkInvitationCodeExists($invitationCode)
    
 {
    
     $user = new User();
    
     $existingCode = $user->where('invitation_code', $invitationCode)->find();
    
     if ($existingCode){
    
     return true;
    
     }
    
     return false;
    
 }
    
    
    
    
    php
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/DkJbp7w9MhL01NgvX6nYrj38uxIo.png)
解析:

generateInvitationCode() 函数用于生成邀请码。它接受一个可选参数 $i,表示循环次数。如果未提供参数,则默认为 1。

generateInvitationCode() 函数中,我们首先定义了邀请码的范围,即从 10000 到 99999。

如果循环次数 $i 大于 50,则我们需要扩充邀请码的范围。我们使用 bcdiv() 函数计算 $i 除以 50 的商,并将结果存储在 $multiple 变量中。然后,我们使用 str_repeat() 函数将 $multiple 个 0 和 9 分别拼接到 $start$end 变量中。

接下来,我们使用 rand() 函数在 $start$end 之间生成一个随机数,并将其存储在 $invitationCode 变量中。

然后,我们使用 checkInvitationCodeExists() 函数检查邀请码是否已经存在于数据库中。如果邀请码已经存在,则我们递归调用 generateInvitationCode() 函数,并将 $i 参数加 1。

最后,我们返回生成的邀请码。

checkInvitationCodeExists() 函数用于检查邀请码是否已经存在于数据库中。它接受一个参数 $invitationCode,表示要检查的邀请码。

checkInvitationCodeExists() 函数中,我们首先创建一个新的 User 对象。然后,我们使用 where() 方法查询数据库中是否存在与 $invitationCode 相匹配的邀请码。如果存在,则返回 true,否则返回 false

缺点:

可能会造成多次的user表查询过于频繁

2.建表建库,每次从表中随机抽取一条,用完时扩充


表结构
复制代码
 SET NAMES utf8mb4;

    
 SET FOREIGN_KEY_CHECKS = 0;
    
  
    
 -- ----------------------------
    
 -- Table structure for fa_activation_key
    
 -- ----------------------------
    
 DROP TABLE IF EXISTS `fa_activation_key`;
    
 CREATE TABLE `fa_activation_key`  (
    
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
    
   `status` int(2) NOT NULL DEFAULT 0 COMMENT '0未使用1已使用',
    
   PRIMARY KEY (`id`) USING BTREE,
    
   UNIQUE INDEX `idx`(`id`) USING BTREE,
    
   INDEX `statusx`(`status`) USING BTREE
    
 ) ENGINE = InnoDB AUTO_INCREMENT = 110000 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
  
    
 SET FOREIGN_KEY_CHECKS = 1;
    
    
    
    
    sql
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/zXUSnwCpTvlqFR8b4WOyexmi9Zhg.png)
表视图
代码
复制代码
 /** * 查找一个随机邀请码
    
  */
    
 function findKey(){
    
     return Db::name('activation_key')
    
     ->where('status',0)
    
     ->orderRaw('rand()')
    
     ->limit(1)
    
     ->value('id');
    
 }
    
  
    
 /** * 生成邀请码
    
  */
    
 function activationkey(){
    
     $key = findKey();
    
     
    
     if(empty($key)){
    
     // 如果邀请码用完了,进行库扩建
    
     $res = createActivationKey();
    
     if($res){
    
         // 扩建以后再随机获取一个
    
         $key = findKey();
    
     }
    
     }
    
     // 把邀请码改为已使用状态
    
     Db::name('activation_key')->where('id',$key)->update(['status'=>1]);
    
  
    
     return $key;
    
 }
    
  
    
 /** * 建立邀请码库
    
  */
    
 function createActivationKey(){
    
     // 已使用完的邀请码库最大值,从这个值开始往上扩建
    
     $start = Db::name('activation_key')->order('id desc')->value('id');
    
     if(empty($start)){
    
     // 邀请码库为空从10000开始建库
    
     $start = 10000;
    
     }else{
    
     // 邀请码用完从最大值+1开始建库
    
     $start = bcadd($start,1);
    
     }
    
     // 每次扩充99999个邀请码
    
     $end = bcadd($start,99999);
    
  
    
     $arr = [];
    
     for ($i=$start; $i<=$end; $i++){
    
     $arr[] = ['id' => $i];
    
     }
    
     // 先把作废的删除掉
    
     Db::name('activation_key')->where('status', 1)->delete();
    
     
    
     // 批量插入邀请码
    
     Db::name('activation_key')
    
     ->data($arr)
    
     ->limit(100)
    
     ->insertAll($arr);
    
     return true;
    
 }
    
    
    
    
    php
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/Mqv1bBF5QtSUurHZlDiCYexPkEpJ.png)
解析

findKey() 函数用于查找一个随机邀请码。它使用 Db::name('activation_key') 查询数据库中状态为 0 的邀请码,并按随机顺序排序,使用 limit(1) 限制只返回一个邀请码。最后,使用 value('id') 获取邀请码的 ID。

activationkey() 函数用于生成邀请码。它首先调用 findKey() 函数查找一个随机邀请码。如果 findKey() 返回的邀请码为空,则表示邀请码库已经用完,需要扩建邀请码库。然后调用 createActivationKey() 函数进行扩建。如果扩建成功,再次调用 findKey() 函数查找一个随机邀请码。最后,将邀请码的状态更新为 1,表示已经使用过。

createActivationKey() 函数用于建立邀请码库。它首先获取当前已使用过的邀请码库的最大值,如果没有找到,则从 10000 开始建立邀请码库。然后,每次扩充 99999 个邀请码。接下来,创建一个包含所有邀请码的数组,并先删除状态为 1 的邀请码。最后,批量插入邀请码。

缺点

需要单独的建表建库,每次都需要调用mysql获取,比直接随机生成效率低,但相比第一种在后期会节约一定的时间,减少查询次数

结论:

方法1,2各有优缺,但都不是很好的解决办法,目前没有想到其他的效率高的办法,有好思路的朋友欢迎指点交流一下

全部评论 (0)

还没有任何评论哟~