uniqid()
返回的结果类似于'492607b0ee414'
。我希望得到类似于TinyURL提供的'64k8ra'
的字符串,越短越好。唯一的要求是它不应该有明显的顺序,并且应该比看起来像随机数字序列的字符更漂亮。字母比数字更受欢迎,理想情况下不会混合大小写字母。由于条目数量不会很多(最多10000个左右),碰撞的风险并不是很大。
欢迎任何建议。uniqid()
返回的结果类似于'492607b0ee414'
。我希望得到类似于TinyURL提供的'64k8ra'
的字符串,越短越好。唯一的要求是它不应该有明显的顺序,并且应该比看起来像随机数字序列的字符更漂亮。字母比数字更受欢迎,理想情况下不会混合大小写字母。由于条目数量不会很多(最多10000个左右),碰撞的风险并不是很大。
欢迎任何建议。编写一个小函数,根据给定的长度返回随机字母:
<?php
function generate_random_letters($length) {
$random = '';
for ($i = 0; $i < $length; $i++) {
$random .= chr(rand(ord('a'), ord('z')));
}
return $random;
}
然后你需要调用它,直到它变得唯一,在伪代码中,取决于您在哪里存储该信息:
do {
$unique = generate_random_letters(6);
} while (is_in_table($unique));
add_to_table($unique);
你可能还希望确保这些字母在任何字典中都不能组成一个单词,无论是整个英语词典还是仅包含脏话的字典,以避免顾客感到不适。
编辑:如果你想要使用此方法来处理大量项,可能会变得非常慢,因为会有更多的冲突(获取已经在表中的ID)。当然,你需要一个索引表,并调整ID中字母的数量以避免冲突。在这种情况下,使用6个字母,你将有26 ^ 6 = 308915776个可能的唯一ID(减去不良单词),这应该足够满足你10000个的需求。
编辑: 如果你想要字母和数字的组合,可以使用以下代码:
$random .= rand(0, 1) ? rand(0, 9) : chr(rand(ord('a'), ord('z')));
ord('a')
和 ord('z')
放在循环外,以避免在每次迭代时调用该函数。 - Scalpweb$random .= rand(0,35) < 10 ? rand(0,9) : chr(rand(ord('a'), ord('z')));
。 - Buttle Butkus@gen_uuid() 由gord编写。
preg_replace存在一些讨厌的UTF-8问题,导致UID有时会包含“+”或“/”。 为了解决这个问题,您必须明确地将模式设置为UTF-8。
function gen_uuid($len=8) {
$hex = md5("yourSaltHere" . uniqid("", true));
$pack = pack('H*', $hex);
$tmp = base64_encode($pack);
$uid = preg_replace("#(*UTF8)[^A-Za-z0-9]#", "", $tmp);
$len = max(4, min(128, $len));
while (strlen($uid) < $len)
$uid .= gen_uuid(22);
return substr($uid, 0, $len);
}
花了我相当长的时间才找到这个,或许能帮助其他人避免头疼
你可以用更少的代码实现此目标:
function gen_uid($l=10){
return substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"), 0, $l);
}
结果 (示例):
function gen_uid($l=10){ $str = ""; for ($x=0;$x<$l;$x++) $str .= substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyz"), 0, 1); return $str; }
- LobsterMan$character_list
是什么(alnum等),你只需要取一个随机的单字母子串:$str .= substr($character_list,rand(0,61),1);
(我用[0-9A-Za-z]
测试了一下,共62个字符)。如果速度很重要,我运行了这个版本100万次,时间为4.57-4.93秒,而你的版本则需要9.96-10.34秒。 - Buttle Butkus获得可靠唯一ID的方法有两种:使其变得非常长和多变,以使冲突的机会极小(例如GUID),或将所有生成的ID存储在表中进行查找(无论是在内存中还是在DB或文件中)以验证其唯一性。
如果您真的想知道如何生成这样一个短键并保证其唯一性而不进行任何重复检查,那么答案是,您不能。
这是我用于生成任意长度随机base62字符串的例程...
调用gen_uuid()
将返回像WJX0u0jV,E9EMaZ3P
之类的字符串。
默认情况下,此函数返回8个数字,因此可以提供64^8或大约10^14个空间,这通常足以使冲突非常少。
对于更大或更小的字符串,请传递所需的$len。长度没有限制,我一直添加到满意为止[最高安全限制为128个字符,可以删除]。
请注意,在md5 [或如果您喜欢,则为sha1]中使用随机盐值,以便它不能轻松地进行反向工程。
我在网上没有找到可靠的base62转换方法,因此采用了从base64结果中去除字符的方法。
在BSD许可证下免费使用,祝你使用愉快!
function gen_uuid($len=8)
{
$hex = md5("your_random_salt_here_31415" . uniqid("", true));
$pack = pack('H*', $hex);
$uid = base64_encode($pack); // max 22 chars
$uid = ereg_replace("[^A-Za-z0-9]", "", $uid); // mixed case
//$uid = ereg_replace("[^A-Z0-9]", "", strtoupper($uid)); // uppercase only
if ($len<4)
$len=4;
if ($len>128)
$len=128; // prevent silliness, can remove
while (strlen($uid)<$len)
$uid = $uid . gen_uuid(22); // append until length achieved
return substr($uid, 0, $len);
}
非常简单的解决方案:
使用以下方法生成唯一ID:
$id = 100;
base_convert($id, 10, 36);
再次获取原始值:
intval($str,36);
我不能为此内容负责,因为它来自于另一个stackoverflow页面。但是,我认为这个解决方案非常优雅和棒,值得将其复制到本主题供其他人参考。
function toUId($baseId, $multiplier = 1) {
return base_convert($baseId * $multiplier, 10, 36);
}
function fromUId($uid, $multiplier = 1) {
return (int) base_convert($uid, 36, 10) / $multiplier;
}
echo toUId(10000, 11111);
1u5h0w
echo fromUId('1u5h0w', 11111);
10000
我想到了一个非常酷的解决方案,可以在不进行唯一性检查的情况下完成此操作。为了给未来的访问者提供帮助,我想分享一下我的方法。
计数器是保证唯一性的一种非常简单的方法,或者如果您正在使用数据库,则主键也可以保证唯一性。问题在于它看起来很丑陋,而且可能存在漏洞。所以我将序列与密码混合在一起。由于密码可以反转,因此我知道每个id都是唯一的,同时看起来是随机的。
这是Python而不是PHP,但我上传了代码: https://github.com/adecker89/Tiny-Unique-Identifiers
字母很漂亮,数字很丑。
您想要随机字符串,但不想要"丑陋"的随机字符串?
创建一个随机数并以字母样式(26进制)打印出来,就像航空公司给出的预订“编号”。
据我所知,PHP中没有通用的基本转换函数,因此您需要自己编写那一部分代码。
另一个选择:使用uniqid()
并摆脱数字。
function strip_digits_from_string($string) {
return preg_replace('/[0-9]/', '', $string);
}
function replace_digits_with_letters($string) {
return strtr($string, '0123456789', 'abcdefghij');
}
请查看这篇文章
该文章解释了如何从您的 bdd ids 生成短唯一 id,就像 youtube 一样。
实际上,该文章中的函数与 php 函数 base_convert 非常相关,它将数字从一种基数转换为另一种基数(但仅限于36进制)。
Random::alphaLowercaseString(6)
来获取,或者根据你的需要选择长度为 8 或 10。 - caw