Skip to content

Instantly share code, notes, and snippets.

@he426100
Forked from guanguans/InviteCode.php
Last active February 5, 2021 16:57
Show Gist options
  • Select an option

  • Save he426100/989b42f341f49cb4e398e6467160ec72 to your computer and use it in GitHub Desktop.

Select an option

Save he426100/989b42f341f49cb4e398e6467160ec72 to your computer and use it in GitHub Desktop.
InviteCode.php
<?php
declare(strict_types=1);
namespace org;
/**
* Class InviteCode
* 邀请码生成类
* @link https://gist.github.com/guanguans/52b9136e86c1a86ab0d51747e841537d
* @link https://www.albinwong.com/6x174dD7ZyjPQvpX.html
* @link https://xjwblog.com/?p=645
* @link https://learnku.com/articles/51069
*
* ```
* $inviteCode = new org\InviteCode();
* var_dump($inviteCode->encode(1)); // string(7) "ONEQA1M"
* var_dump($inviteCode->decode("ONEQA1M")); // int(1)
* ```
*
*/
final class InviteCode
{
/**
* @var string
*/
private $key; // Array.from(s).sort(() => Math.random() > 0.5 ? -1 : 1).join('')
/**
* @var int
*/
private $octal;
/**
* @var int
*/
private $base = 0;
public function __construct(string $key = 'BM2DYTOH8ZC7EN3XJ16LISPGWQ5UKRFVA9', int $base = 9876543210)
{
// 注意这个key里面不能出现数字 0,否则当`求模=0`会重复的
$this->key = $this->clear($key);
// 多少进制
$this->octal = strlen($this->key);
// 加一个基数,避免出现补零
$this->base = $base;
}
/**
* encode id to code
*
* @param integer $id
* @param integer $length
* @return string
*/
public function encode(int $id, int $length = 7): string
{
$code = '';
// 转进制
$num = $this->base + $id;
while ($num > 0) {
$mod = $num % $this->octal; // 求模
$num = ($num - $mod) / $this->octal;
$code = $this->key[$mod] . $code;
}
return str_pad($code, $length, '0', STR_PAD_LEFT); // 不足用0补充;
}
/**
* decode code to id
*
* @param string $code
* @return integer
*/
public function decode(string $code): int
{
//移除左侧的 0
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($this->key, $code[$i]) * pow($this->octal, $i);
}
return (int)$num - $this->base;
}
/**
* @param string $str
*
* @return string
*/
private function clear(string $str): string
{
$uniqueStr = trim(implode('', array_unique(str_split($str))));
return str_replace('0', '', $uniqueStr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment