需求描述:根据⽤户id⽣成与之对应的唯⼀邀请码,范围为‘0-9A-Z’。
喷嘴清洗这个需求的重点在于加粗的部分,也就是要能够根据邀请码反推出⽤户ID,这样邀请码就不⽤⼊库了,在⽤户量很⼤的情况下,性能可以得到不⼩的提升。
错误思路
随机⽣成⼀个字符串,再将⽤户id拼接到字符串后⾯,但是这样id就太明显了,容易暴露,⽽且如果id很长的话,会导致邀请码很长,不利于⽤户使⽤。
所以可以将⽤户id插⼊到⽣成的字符串中,隔⼀个字符插⼊⼀个id的数字,这样id混合在字符串中,不容易暴露,但是长度问题并没有得到优化,于是把隔⼀个字符插⼊⼀个id的数字改为隔⼀个字符插⼊两个id的数字。然⽽长度好像并没有受到太⼤的影响。 正解
思考:⼀个10进制的数字短还是⼀个16进制的数字短?
肯定是16进制相对短⼀些,所以我们可以直接把⽤户id转成10+26=36进制的不就可以了吗?具体代码如下:
function createCode($user_id)
{
static $source_string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$num = $user_id;
$code = '';tsf过载保护
while($num)
{
$mod = $num % 36;
焗油机
$num = ($num - $mod) / 36;
$code = $source_string[$mod].$code;
}
return $code;
}
邀请码保证了唯⼀性,并且长度不会太长,⽤户id也能够根据邀请码反推出来,但是有⼀点不好的是,别⼈也可以根据邀请码去反推出user_id,因此,我们需要做⼀些优化。
优化
攀岩板
把0剔除,当做补位符号,⽐如⼩于四位的邀请码在⾼位补0,这样36进制就变成了35进制,然后把字符串顺序打乱,这样,在不知
道$source_string的情况下,是没办法解出正确的user_id的。
代码如下:
function createCode($user_id) {
static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ';
$num = $user_id;
$code = '';
while ( $num > 0) {
$mod = $num % 35;
$num = ($num - $mod) / 35;
$code = $source_string[$mod].$code;
}
if(empty($code[3]))
$code = str_pad($code,4,'0',STR_PAD_LEFT);
return $code;
}
这样,对应user_id的唯⼀邀请码就⽣成了,再附⼀个解码函数:
function decode($code) {
static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ';
if (strrpos($code, '0') !== false)
$code = substr($code, strrpos($code, '0')+1);
$len = strlen($code);抗氧化植物素
$code = strrev($code);
$num = 0;
for ($i=0; $i < $len; $i++) {
$num += strpos($source_string, $code[$i]) * pow(35, $i);
手动加油泵}
return $num;
}