我想在我的小型预订系统(用于产品)的智能模板中使用php uniqid()来生成一个UNIQUE值,该值可用于预订号码。 默认的uniqid()对我来说有点太长了,怎么能让它像5-6个字符一样?
答案 0 :(得分:1)
暂定答案:
<?php
function toBase(/* positiv integer*/ $n, array $alphabet) {
$retval = '';
do {
$retval .= $alphabet[ $n%count($alphabet) ];
$n = intval( $n / count($alphabet) );
}
while( ($n=intval($n)) > 0);
return $retval;
}
function getCode() {
static $alphabet = null;
if( $alphabet==null) {
$alphabet = str_split('3479ACEFHJKLMNPRTUVWXY');
}
// get a random number
// and "encode" it using the alphabet
$code = toBase(mt_rand(), $alphabet);
// this might be both
// - too long
// - and too short*
// so first get the last 6 characters (if there are that much)
$code = substr($code, -6);
// and if there wasn't, pad them with 'zeros' (according to the alphabet that's a '3')
$code = str_pad($code, 6, $alphabet[0]);
return $code;
// *) the "too short" part could be avoided via mt_rand(22^6, ...)
// but I want to keep it in the range of a 32bit signed integer
}
getCode()为您提供类似
的代码YFTRXA
MRMTMV
YC9HVN
VWCAUE
JEVXUF
WWMEYU
KLWAML
YCKE3V
37KJ3P
ME9EKU
我通过
测试了getCode()(一次)function testCodes() {
$codes = [];
for($i=0; $i<2000; $i++) {
$codes[] = getCode();
}
$withoutCollisions = array_unique($codes);
return count($codes)-count($withoutCollisions);
}
$collisions = [];
for($i=0; $i<5000; $i++) {
$c = testCodes();
if ( !isset($collisions[$c]) ) {
$collisions[$c] = 0;
}
$collisions[$c] += 1;
}
var_dump($collisions);
,输出
array(3) {
[0]=>
int(4899)
[1]=>
int(100)
[2]=>
int(1)
}
所以有碰撞(一组2000个代码有一个或两个双联)但我会说你应该试图在球场中实现它。碰撞率足够低,这样你甚至可以在该领域的数据库中放置一个独特的约束,只需再次尝试碰撞。
....但是可以随意接触https://security.stackexchange.com/并将此算法分解成碎片; - )