加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 多个uniqid()调用不是唯一的

发布时间:2020-12-13 22:11:17 所属栏目:PHP教程 来源:网络整理
导读:我有一个有趣的例子,当在XAMPP上本地托管时,对uniqid()的多次重复调用不会生成唯一编号.独特的id在5-20次之间重复,然后神秘地改变. 但是,作为一个有趣的转折,代码在我们的生产服务器上完美运行. 所以这就是我正在做的事情:我正在创建一个包装器,当单击它时,
我有一个有趣的例子,当在XAMPP上本地托管时,对uniqid()的多次重复调用不会生成唯一编号.独特的id在5-20次之间重复,然后神秘地改变.

但是,作为一个有趣的转折,代码在我们的生产服务器上完美运行.

所以这就是我正在做的事情:我正在创建一个包装器,当单击它时,通过简单的javascript函数隐藏/取消隐藏div中的子内容.由于可动态div是动态生成的,因此它由PHP生成的唯一ID引用.

该问题的一个例子如下:

// Replace something like '[element] => <newline> (' with <a href="javascript:toggleDisplay('[unique id]');">...</a><div id="[unique id]" style="display: none;">   
$out = preg_replace_callback(
        $regex,function ($matches) {
            $id = uniqid();
            return $matches[1] . "<a class='debug' href='javascript:toggleDisplay("" . $id . "");'>" . $matches[2] . "</a>" . "<div id='" . $id . "' style='display: none'>";
        },$out
    );

javascript函数如下(只是这样你可以看到我在做什么;它完美地工作):

<script language="Javascript">
    function toggleDisplay(id) {
        document.getElementById(id).style.display = (document.getElementById(id).style.display == "block") ? "none" : "block";
    }
</script>'

问题是输出div都具有相同的唯一id(!!),在5-15之间的任何簇中,所以javascript不知道引用什么div.

所以我发现了一些事情:如果我做了类似$id = uniqid()的事情. rand(10000,99999)而不仅仅是$id = uniqid()然后代码再次按预期工作.所以我很确定问题是uniqid()实际上并没有生成一个唯一的id,因为我没有覆盖或重用$id变量.

我发现的另一个有趣的事情是:如果我将microtime()与uniqid()一起回显,则uniqid()仅在microtime()更改时才会更改.对我而言,这感觉就像一条线索.

所以我的问题是:为什么uniqid()有时只生成uniqid()?是不是uniqid()应该生成一个唯一的数字,即使microtime()是相同的?这种行为是记录还是众所周知的?或者还有其他我想念的东西?

我问,因为我使用uniqid()感到不舒服,因为我不了解核心行为.

任何见解将不胜感激.谢谢.

解决方法

uniqid()的结果不能保证是唯一的,你用microtime()的调查确实是一个线索.

根据the manual page for uniqid(),它:

Gets a prefixed unique identifier based on the current time in microseconds.

所以主要的输入确实是当前的“microtime”.但是,它还需要一个额外的参数:

more_entropy
If set to TRUE,uniqid() will add additional entropy (using the combined linear congruential generator) at the end of the return value,which increases the likelihood that the result will be unique.

请注意,即使使用此参数,手册也要注意不要保证唯一性,但与手动使用rand()一样,它会增加一个额外的随机源,这使得冲突更加不可能发生.

为了确认,我们可以看一下the source code for the function,我们可以看到没有more_entropy设置的输出确实只是当前微秒时间戳的十六进制表示.一件有趣的事情是:

#if HAVE_USLEEP && !defined(PHP_WIN32)
    if (!more_entropy) {
#if defined(__CYGWIN__)
        php_error_docref(NULL,E_WARNING,"You must use 'more entropy' under CYGWIN");
        RETURN_FALSE;
#else
        usleep(1);
#endif
    }
#endif

因此,如果您不在Windows下,该函数实际上会尝试睡眠一微秒,以强制后续值不同.

这使得连续多次运行uniqid()成为一个坏主意,因为如果它成功了,它会慢慢地运行. (需要一个微秒的睡眠,或者调用随机数发生器.)

一个更好的想法是使用它一次生成一个任意前缀,然后简单地为每个项目增加一个计数器,这可能看起来像这样:

$id_prefix = uniqid();
$id_suffix = 0;
$out = preg_replace_callback(
        $regex,function ($matches) use ($id_prefix,&$id_suffix) {
            $id = $id_prefix . $id_suffix;
            $id_suffix ++;
            return $matches[1] . '... some html ...' . $id . ' ... ';
        },$out
);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读