我想在我的小型预订系统(针对产品)的智能模板中使用php uniqid()来生成一个唯一的值,该值将成为一个预订编号。默认的uniqid()对我来说有点太长了,我怎么才能让它像5-6个字符?
发布于 2015-09-25 21:10:24
试探性的回答:
<?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个代码,有一个或两个二元组),但我想说你想要实现的目标是在球场上。冲突率足够低,因此您甚至可以在数据库中的该字段上放置一个唯一的约束,然后简单地在collison上再次尝试。
....BUT可以随意使用https://security.stackexchange.com/,并将此算法分解为碎片;-)
https://stackoverflow.com/questions/32781381
复制相似问题