سؤال

لذلك كنت أفعل بعض الحفر وحاولت أن أحاول قطعة معا وظيفة تنشئ UUID V4 صالحة في PHP. هذا هو الأقرب الذي تمكنت من المجيء. معرفتي في العاملين العشرون والثنائيين والثنائيين، وكأنهم مثل غير موجود تقريبا. هذه الوظيفة تنشئ UUID V4 صالحة حتى منطقة واحدة. يجب أن يكون UUID V4 في شكل:

XXXXXXXX-XXXX-4XXX-Y.xxx-xxxxxxxxx.

أين Y. هو 8 أو 9 أو أ أو ب. حيث تفشل المهام كما لا تلتزم بذلك.

كنت آمل أن يكون هناك معرفة أكثر معرفة أكثر مني في هذا المجال بيد ويساعدني في حل هذه الوظيفة حتى تلتزم بهذه القاعدة.

الوظيفة هي كما يلي:

<?php

function gen_uuid() {
 $uuid = array(
  'time_low'  => 0,
  'time_mid'  => 0,
  'time_hi'  => 0,
  'clock_seq_hi' => 0,
  'clock_seq_low' => 0,
  'node'   => array()
 );

 $uuid['time_low'] = mt_rand(0, 0xffff) + (mt_rand(0, 0xffff) << 16);
 $uuid['time_mid'] = mt_rand(0, 0xffff);
 $uuid['time_hi'] = (4 << 12) | (mt_rand(0, 0x1000));
 $uuid['clock_seq_hi'] = (1 << 7) | (mt_rand(0, 128));
 $uuid['clock_seq_low'] = mt_rand(0, 255);

 for ($i = 0; $i < 6; $i++) {
  $uuid['node'][$i] = mt_rand(0, 255);
 }

 $uuid = sprintf('%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x',
  $uuid['time_low'],
  $uuid['time_mid'],
  $uuid['time_hi'],
  $uuid['clock_seq_hi'],
  $uuid['clock_seq_low'],
  $uuid['node'][0],
  $uuid['node'][1],
  $uuid['node'][2],
  $uuid['node'][3],
  $uuid['node'][4],
  $uuid['node'][5]
 );

 return $uuid;
}

?>

شكرا لأي شخص يمكن أن يساعدني.

هل كانت مفيدة؟

المحلول

مأخوذ من هذه التعليق على دليل PHP، يمكنك استخدام هذا:

function gen_uuid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        // 32 bits for "time_low"
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),

        // 16 bits for "time_mid"
        mt_rand( 0, 0xffff ),

        // 16 bits for "time_hi_and_version",
        // four most significant bits holds version number 4
        mt_rand( 0, 0x0fff ) | 0x4000,

        // 16 bits, 8 bits for "clk_seq_hi_res",
        // 8 bits for "clk_seq_low",
        // two most significant bits holds zero and one for variant DCE1.1
        mt_rand( 0, 0x3fff ) | 0x8000,

        // 48 bits for "node"
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
    );
}

نصائح أخرى

بدلا من تقسيمه إلى الحقول الفردية، من الأسهل إنشاء كتلة عشوائية من البيانات وتغيير مواقع البايت الفردية. يجب عليك أيضا استخدام مولد أرقام عشوائي أفضل من MT_RAND ().

بالنسبة الى RFC 4122 - القسم 4.4, تحتاج إلى تغيير هذه الحقول:

  1. time_hi_and_version (بت 4-7 من الثماني السابع)،
  2. clock_seq_hi_and_reserved (بت 6 و 7 من الثماني التاسع)

يجب أن تكون كل قطعة 122 الأخرى عشوائية بما فيه الكفاية.

ينشئ النهج التالي 128 بت من البيانات العشوائية باستخدام openssl_random_pseudo_bytes(), ، يجعل التباديلات على الأمثيات ثم يستخدم bin2hex() و vsprintf() للقيام بالتنسيق النهائي.

function guidv4($data)
{
    assert(strlen($data) == 16);

    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

echo guidv4(openssl_random_pseudo_bytes(16));

مع PHP 7، توليد تسلسل البايت عشوائي هو أكثر بساطة باستخدام random_bytes():

function guidv4($data = null)
{
    $data = $data ?? random_bytes(16);
    // ...
}

أي شخص يستخدم ملحن التبعيات، قد ترغب في النظر في هذه المكتبة: https://github.com/ramsey/uuid.

لا تحصل على أي أسهل من هذا:

Uuid::uuid4();

على أنظمة UNIX، استخدم نواة النظام لتوليد UUID لك.

file_get_contents('/proc/sys/kernel/random/uuid')

الائتمان Samveen على https://serverfault.com/a/529319/210994.

ملاحظة!: استخدام هذه الطريقة للحصول على UUID في الواقع استنفاد تجمع Entropy بسرعة كبيرة! أود تجنب استخدام هذا حيث سيتم استدعاء بشكل متكرر.

في بحثي عن إنشاء OUID A V4، جئت أولا إلى هذه الصفحة، ثم وجدت هذا http://php.net/manual/en/function.com-create-guid.php.

function guidv4()
{
    if (function_exists('com_create_guid') === true)
        return trim(com_create_guid(), '{}');

    $data = openssl_random_pseudo_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

الائتمان: pavel.volyntsev.

تحرير: للتوضيح، ستمنحك هذه الوظيفة دائما UUID V4 (PHP> = 5.3.0).

عند توفر وظيفة COM_CREATE_GUID (عادة فقط على Windows)، سيستخدم ذلك ويطرب الأقواس المجعد.

إذا لم يكن موجودا (Linux)، فسوف يسقط على وظيفة Openssl_random_random_pseudo_byto_bytes هذه، فسيتم بعد ذلك استخدام VSPRINTF لتنسيقه في UUID V4.

إجابتي تستند إلى التعليق تعليق المستخدم UNIQID لكنه يستخدم openssl_random_pseudo_bytes. وظيفة لتوليد سلسلة عشوائية بدلا من القراءة من /dev/urandom

function guid()
{
    $randomString = openssl_random_pseudo_bytes(16);
    $time_low = bin2hex(substr($randomString, 0, 4));
    $time_mid = bin2hex(substr($randomString, 4, 2));
    $time_hi_and_version = bin2hex(substr($randomString, 6, 2));
    $clock_seq_hi_and_reserved = bin2hex(substr($randomString, 8, 2));
    $node = bin2hex(substr($randomString, 10, 6));

    /**
     * Set the four most significant bits (bits 12 through 15) of the
     * time_hi_and_version field to the 4-bit version number from
     * Section 4.1.3.
     * @see http://tools.ietf.org/html/rfc4122#section-4.1.3
    */
    $time_hi_and_version = hexdec($time_hi_and_version);
    $time_hi_and_version = $time_hi_and_version >> 4;
    $time_hi_and_version = $time_hi_and_version | 0x4000;

    /**
     * Set the two most significant bits (bits 6 and 7) of the
     * clock_seq_hi_and_reserved to zero and one, respectively.
     */
    $clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
    $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2;
    $clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;

    return sprintf('%08s-%04s-%04x-%04x-%012s', $time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
} // guid

إذا كنت تستخدم CakePHP يمكنك استخدام طريقةهم CakeText::uuid(); من caketext. فئة لتوليد uuid RFC4122.

مستوحاة من بروفاإجابة هنا.

preg_replace_callback('/[xy]/', function ($matches)
{
  return dechex('x' == $matches[0] ? mt_rand(0, 15) : (mt_rand(0, 15) & 0x3 | 0x8));
}
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');

أو إذا لم تتمكن من استخدام وظائف مجهولة.

preg_replace_callback('/[xy]/', create_function(
  '$matches',
  'return dechex("x" == $matches[0] ? mt_rand(0, 15) : (mt_rand(0, 15) & 0x3 | 0x8));'
)
, 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');

بعد البحث عن نفس الشيء بالضبط و تقريبيا تنفيذ نسخة من هذا بنفسي، اعتقدت أنه كان الأمر يستحق الذكر لذلك، إذا كنت تفعل ذلك داخل وورد الإطار، WP لديه وظيفته السوبر مفيدة لهذا الشيء بالضبط:

$myUUID = wp_generate_uuid4();

يمكنك قراءة الوصف والمصدر هنا.

تباين طفيف على إجابة جاك لإضافة دعم ل PHP <7:

// Get an RFC-4122 compliant globaly unique identifier
function get_guid() {
    $data = PHP_MAJOR_VERSION < 7 ? openssl_random_pseudo_bytes(16) : random_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40);    // Set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80);    // Set bits 6-7 to 10
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

من توم، http://www.php.net/manual/en/function.uniqid.php.

$r = unpack('v*', fread(fopen('/dev/random', 'r'),16));
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    $r[1], $r[2], $r[3], $r[4] & 0x0fff | 0x4000,
    $r[5] & 0x3fff | 0x8000, $r[6], $r[7], $r[8])

ماذا عن استخدام MySQL لتوليد UUID لك؟

$conn = new mysqli($servername, $username, $password, $dbname, $port);

$query = 'SELECT UUID()';
echo $conn->query($query)->fetch_row()[0];

أنا متأكد من أن هناك طريقة أكثر أناقة للقيام بالتحويل من ثنائي إلى عشري 4xxx و yxxx أجزاء. ولكن إذا كنت ترغب في استخدام openssl_random_pseudo_bytes كما مولد الأرقام الآمنة الشديدة، هذا هو ما أستخدمه:

return sprintf('%s-%s-%04x-%04x-%s',
    bin2hex(openssl_random_pseudo_bytes(4)),
    bin2hex(openssl_random_pseudo_bytes(2)),
    hexdec(bin2hex(openssl_random_pseudo_bytes(2))) & 0x0fff | 0x4000,
    hexdec(bin2hex(openssl_random_pseudo_bytes(2))) & 0x3fff | 0x8000,
    bin2hex(openssl_random_pseudo_bytes(6))
    );
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top