一個10進制的數字短還是一個16進制的數字短?
肯定是16進制相對短一些,所以我們可以直接把用戶id轉成10+26=36進制的不就可以了嗎?具體代碼如下:
function createCode($user_id)
{
static $source_string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$num = $user_id;
$code = '';
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;
}