目录
前言:
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;
}
-
解析:
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;
-
表视图
-
代码
/*** 查找一个随机邀请码*/
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;
}
-
解析
findKey()
函数用于查找一个随机邀请码。它使用Db::name('activation_key')
查询数据库中状态为 0 的邀请码,并按随机顺序排序,使用limit(1)
限制只返回一个邀请码。最后,使用value('id')
获取邀请码的 ID。
activationkey()
函数用于生成邀请码。它首先调用findKey()
函数查找一个随机邀请码。如果findKey()
返回的邀请码为空,则表示邀请码库已经用完,需要扩建邀请码库。然后调用createActivationKey()
函数进行扩建。如果扩建成功,再次调用findKey()
函数查找一个随机邀请码。最后,将邀请码的状态更新为 1,表示已经使用过。
createActivationKey()
函数用于建立邀请码库。它首先获取当前已使用过的邀请码库的最大值,如果没有找到,则从 10000 开始建立邀请码库。然后,每次扩充 99999 个邀请码。接下来,创建一个包含所有邀请码的数组,并先删除状态为 1 的邀请码。最后,批量插入邀请码。
-
缺点
需要单独的建表建库,每次都需要调用mysql获取,比直接随机生成效率低,但相比第一种在后期会节约一定的时间,减少查询次数
结论:
方法1,2各有优缺,但都不是很好的解决办法,目前没有想到其他的效率高的办法,有好思路的朋友欢迎指点交流一下