如何使uniqid更短

时间:2015-09-25 11:40:20

标签: php smarty

我想在我的小型预订系统(用于产品)的智能模板中使用php uniqid()来生成一个UNIQUE值,该值可用于预订号码。 默认的uniqid()对我来说有点太长了,怎么能让它像5-6个字符一样?

1 个答案:

答案 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/并将此算法分解成碎片; - )