1
|
|
|
<?php |
2
|
|
|
namespace Fwolf\Util\Uuid; |
3
|
|
|
|
4
|
|
|
use Fwolf\Util\BaseConverter\BaseConverterAwareTrait; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* UUID generator using base-62 character (0-9a-zA-Z) |
8
|
|
|
* |
9
|
|
|
* |
10
|
|
|
* second: 6 chars, seconds in microtime. |
11
|
|
|
* base_convert('ZZZZZZ', 62, 10) = 56800235583 = 3769-12-05 11:13:03 |
12
|
|
|
* base_convert('100000', 62, 10) = 916132832 = 1999-01-12 17:20:32 |
13
|
|
|
* |
14
|
|
|
* microsecond: 4 chars, micro-second in microtime, multiple 1000000. |
15
|
|
|
* base_convert(999999, 10, 62) = 4c91 |
16
|
|
|
* |
17
|
|
|
* group: 2 chars |
18
|
|
|
* base_convert('zz', 62, 10) = 3843, enough to group server. |
19
|
|
|
* |
20
|
|
|
* random: 6 chars |
21
|
|
|
* 62^6 = 56800235584, about 13x of 16^8 = 4294967296, |
22
|
|
|
* and microsecond is 100x of general UUID. |
23
|
|
|
* (Notice: base_convert() does not allow base greater than 36.) |
24
|
|
|
* |
25
|
|
|
* Notice: Mix of a-zA-Z may not suit for Mysql UUID, because Mysql default |
26
|
|
|
* compare string CASE INSENSITIVE. |
27
|
|
|
* |
28
|
|
|
* @copyright Copyright 2013-2016 Fwolf |
29
|
|
|
* @license http://opensource.org/licenses/MIT MIT |
30
|
|
|
*/ |
31
|
|
|
class Base62 extends AbstractTimeBasedUuidGenerator |
32
|
|
|
{ |
33
|
|
|
use BaseConverterAwareTrait; |
34
|
|
|
|
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* {@inheritdoc} |
38
|
|
|
*/ |
39
|
|
|
const LENGTH = 24; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* {@inheritdoc} |
43
|
|
|
*/ |
44
|
|
|
const LENGTH_SECOND = 6; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* {@inheritdoc} |
48
|
|
|
*/ |
49
|
|
|
const LENGTH_MICROSECOND = 4; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* {@inheritdoc} |
53
|
|
|
*/ |
54
|
|
|
const LENGTH_GROUP = 2; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* {@inheritdoc} |
58
|
|
|
*/ |
59
|
|
|
const LENGTH_CUSTOM = 6; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* {@inheritdoc} |
63
|
|
|
*/ |
64
|
|
|
const LENGTH_RANDOM = 6; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* {@inheritdoc} |
68
|
|
|
*/ |
69
|
|
|
const LENGTH_CHECK_DIGIT = 0; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* {@inheritdoc} |
73
|
|
|
*/ |
74
|
|
|
const SEPARATOR = ''; |
75
|
|
|
|
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* {@inheritdoc} |
79
|
|
|
*/ |
80
|
|
|
public function explain($uuid) |
81
|
|
|
{ |
82
|
|
|
$explanation = parent::explain($uuid); |
83
|
|
|
|
84
|
|
|
$converter = $this->getBaseConverter(); |
85
|
|
|
|
86
|
|
|
$second = $converter->convert($explanation->getSecond(), 62, 10); |
87
|
|
|
$explanation->setSecond(date('Y-m-d H:i:s', $second)); |
88
|
|
|
|
89
|
|
|
$microsecond = |
90
|
|
|
$converter->convert($explanation->getMicrosecond(), 62, 10); |
91
|
|
|
$explanation->setMicrosecond($microsecond); |
92
|
|
|
|
93
|
|
|
return $explanation; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* {@inheritdoc} |
99
|
|
|
* |
100
|
|
|
* Parent method result md5, here only need 9 digit of them. |
101
|
|
|
* base_convert('f{8}', 16, 62) = cOu4kx |
102
|
|
|
* base_convert('f{9}', 16, 62) = 3j1L7jb |
103
|
|
|
*/ |
104
|
|
|
protected function generateCustomPartAuto() |
105
|
|
|
{ |
106
|
|
|
$seed = parent::generateCustomPartAuto(); |
107
|
|
|
$seed = substr($seed, 0, 9); |
108
|
|
|
|
109
|
|
|
$converter = $this->getBaseConverter(); |
110
|
|
|
$custom = $converter->convert($seed, 16, 62); |
111
|
|
|
|
112
|
|
|
// In case convert result not fulfill the length |
113
|
|
|
return $custom . '000000'; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* {@inheritdoc} |
119
|
|
|
*/ |
120
|
|
|
protected function generateRandomPart() |
121
|
|
|
{ |
122
|
|
|
$converter = $this->getBaseConverter(); |
123
|
|
|
|
124
|
|
|
// base_convert('ZZZ', 62, 10) = 238327 |
|
|
|
|
125
|
|
|
// base_convert('100', 62, 10) = 3844 |
|
|
|
|
126
|
|
|
$randomPart = $converter->convert(mt_rand(3844, 238327), 10, 62) . |
127
|
|
|
$converter->convert(mt_rand(0, 238327), 10, 62); |
128
|
|
|
|
129
|
|
|
return $randomPart; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* {@inheritdoc} |
135
|
|
|
*/ |
136
|
|
|
protected function generateTimeParts() |
137
|
|
|
{ |
138
|
|
|
list($microSecond, $second) = explode(' ', microtime()); |
139
|
|
|
|
140
|
|
|
$converter = $this->getBaseConverter(); |
141
|
|
|
|
142
|
|
|
$second = $converter->convert($second, 10, 62); |
143
|
|
|
|
144
|
|
|
$microSecond = round($microSecond * 1000000); |
145
|
|
|
$microSecond = $converter->convert($microSecond, 10, 62); |
146
|
|
|
$microSecond = str_pad( |
147
|
|
|
$microSecond, |
148
|
|
|
static::LENGTH_MICROSECOND, |
149
|
|
|
'0', |
150
|
|
|
STR_PAD_LEFT |
151
|
|
|
); |
152
|
|
|
|
153
|
|
|
return [$second, $microSecond]; |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.