在PHP中为Firebase数据库生成多个GUID

时间:2019-05-18 05:52:36

标签: php json firebase

我在MySQL表中有70,000行。我正在尝试通过导入JSON在Firebase中上传它们。我已将表导出为JSON格式。输出是一个数组。例如,JSON如下-

self.mediaPlayer?.replaceCurrentItem(with: nil)
self.mediaPlayer?.play()

为了在移动应用中正确使用Firebase,我需要将此JSON数据与GUID一起作为对象导入,如下所示-

[
{"question_id":"99","question":"What is your name?"},
{"question_id":"200","question":"What do you do?"}
]

由于行数为70,000(此数据的JSON文件为110 MB);无法单独插入Firebase。 因此,我正在尝试一种生成70,000 GUID的方法,并编辑JSON文件以将每个对象添加到每个对象之前。但是,我被困在这两个地方。我正在使用以下类({ "-Lf64AvZinbjvEQLMzGc" : { "question_id" : 99, "question" : "What is your name?" }, "-Lf64AvZinbjvEQLMzGd" : { "question_id" : 200, "question" : "What do you do?" } } )来生成GUID-

PushId.php

以下是我编写的用于生成70,000 GUID的PHP代码,但显示错误(如果我仅使用它来生成1个GUID,则该代码仍在工作)

<?php

/**
 * Fancy ID generator that creates 20-character string identifiers with the following properties:
 *
 * 1. They're based on timestamp so that they sort *after* any existing ids.
 * 2. They contain 72-bits of random data after the timestamp so that IDs won't collide with other clients' IDs.
 * 3. They sort *lexicographically* (so the timestamp is converted to characters that will sort properly).
 * 4. They're monotonically increasing.  Even if you generate more than one in the same timestamp, the
 *    latter ones will sort after the former ones.  We do this by using the previous random bits
 *    but "incrementing" them by 1 (only in the case of a timestamp collision).
 */
class PushId
{
    /**
     * Modeled after base64 web-safe chars, but ordered by ASCII.
     *
     * @var string
     */
    const PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';

    /**
     * Timestamp of last push, used to prevent local collisions if you push twice in one ms.
     *
     * @var int
     */
    private static $lastPushTime = 0;

    /**
     * We generate 72-bits of randomness which get turned into 12 characters and appended to the
     * timestamp to prevent collisions with other clients.  We store the last characters we
     * generated because in the event of a collision, we'll use those same characters except
     * "incremented" by one.
     *
     * @var array
     */
    private static $lastRandChars = [];

    /**
     * @return string
     */
    public static function generate()
    {
        $now = (int) microtime(true) * 1000;
        $isDuplicateTime = ($now === static::$lastPushTime);
        static::$lastPushTime = $now;

        $timeStampChars = new SplFixedArray(8);
        for ($i = 7; $i >= 0; $i--) {
            $timeStampChars[$i] = substr(self::PUSH_CHARS, $now % 64, 1);
            // NOTE: Can't use << here because javascript will convert to int and lose the upper bits.
            $now = (int) floor($now / 64);
        }

        static::assert($now === 0, 'We should have converted the entire timestamp.');

        $id = implode('', $timeStampChars->toArray());

        if (!$isDuplicateTime) {
            for ($i = 0; $i < 12; $i++) {
                $lastRandChars[$i] = floor(rand(0, 64));
            }
        } else {
            // If the timestamp hasn't changed since last push, use the same random number, except incremented by 1.
            for ($i = 11; $i >= 0 && static::$lastRandChars[$i] === 63; $i--) {
                static::$lastRandChars[$i] = 0;
            }
            static::$lastRandChars[$i]++;
        }
        for ($i = 0; $i < 12; $i++) {
            $id .= substr(self::PUSH_CHARS, $lastRandChars[$i], 1);
        }

        static::assert(strlen($id) === 20, 'Length should be 20.');

        return $id;
    }

    /**
     * @param bool   $condition
     * @param string $message
     */
    private static function assert($condition, $message = '')
    {
        if ($condition !== true) {
            throw new RuntimeException($message);
        }
    }
}

编辑-1 我在生成GUID时遇到的错误是- require_once('PushId.php'); $vars = new PushId(); $my_file = 'TheGUIDs.txt'; $handle = fopen($my_file, 'w') or die('Cannot open file: '.$my_file); $i=1; while($i <= 70000){ $data = $vars->generate(); fwrite($handle, $data); echo $data; $i++; } fclose($handle);

Notice: Undefined offset: 11 in C:\wamp64\www\firebase-json\PushId.php on line 65

第一个GUID已完成,例如在上一次运行中,我得到了Notice: Undefined variable: lastRandChars in C:\wamp64\www\firebase-json\PushId.php on line 71,但是后来我得到了不完整的GUID -Lf8WPlkkNTUjYkIP4WT

1 个答案:

答案 0 :(得分:1)

首先,您在某些地方忘记在static::之前加$lastRandChars

for ($i = 0; $i < 12; $i++) {
    $lastRandChars[$i] = floor(rand(0, 64)); // << here
}
for ($i = 0; $i < 12; $i++) {
    $id .= substr(self::PUSH_CHARS, $lastRandChars[$i], 1); // << and here
}

下一步: 当递增先前的ID时,您错过了您不仅应递增最后一个字符,而且还应递增所有先前的字符(如果它们大于63)。 样本ID顺序:

...
-Lf64AvZinbjvEQLMzGw
-Lf64AvZinbjvEQLMzGx
-Lf64AvZinbjvEQLMzGy
-Lf64AvZinbjvEQLMzGz 
-Lf64AvZinbjvEQLMzH- <<< on this step last char is reset, and previous one is incremented by one
-Lf64AvZinbjvEQLMzH0
-Lf64AvZinbjvEQLMzH1
...
-Lf64AvZinbjvEQLMzzw
-Lf64AvZinbjvEQLMzzx
-Lf64AvZinbjvEQLMzzw
-Lf64AvZinbjvEQLMzzz 
-Lf64AvZinbjvEQLN--- <<< on this step last three chars are reset, and previous one is incremented by one
-Lf64AvZinbjvEQLN--0
-Lf64AvZinbjvEQLN--1
...

修改后的增量逻辑:

// If the timestamp hasn't changed since last push, use the same random number, except incremented by 1.
for ($i = 11; $i >= 0; $i--) {
    $previousIncremented = false;
    for ($j = $i; $j > 0; $j--) {
        if (!$previousIncremented) {
            static::$lastRandChars[$j]++;
        }
        if (static::$lastRandChars[$j] == 64) {
            static::$lastRandChars[$j] = 0;
            static::$lastRandChars[$j - 1]++;
            $previousIncremented = true;
        } else {
            break 2;
        }
    }
}