PHP समारोह v4 UUID उत्पन्न करने के लिए


233

इसलिए मैं चारों ओर कुछ खुदाई कर रहा हूं और मैं एक फ़ंक्शन को एक साथ करने की कोशिश कर रहा हूं जो PHP में एक वैध v4 UUID उत्पन्न करता है। यह निकटतम है जो मैं आने में सक्षम हूं। हेक्स, दशमलव, बाइनरी, पीएचपी के बिटवाइज ऑपरेटरों और इस तरह का मेरा ज्ञान लगभग गैर मौजूद है। यह फ़ंक्शन एक क्षेत्र तक एक मान्य v4 UUID उत्पन्न करता है। एक v4 UUID के रूप में होना चाहिए:

xxxxxxxx-xxxx- 4 xxx- y xxx-xxxxxxxxxxxx

जहाँ y 8, 9, A या B है। यह वह जगह है जहाँ फ़ंक्शन विफल रहता है क्योंकि यह उसका पालन नहीं करता है।

मैं उम्मीद कर रहा था कि इस क्षेत्र में मुझसे अधिक ज्ञान रखने वाला कोई व्यक्ति मुझसे हाथ मिला सकता है और इस कार्य को ठीक करने में मेरी मदद कर सकता है, इसलिए यह उस नियम का पालन करता है।

फ़ंक्शन निम्नानुसार है:

<?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;
}

?>

किसी को भी धन्यवाद जो मेरी मदद कर सकता है।


5
आप लिनक्स पर रहे हैं और आप के साथ उन्हें generete सकते हैं यदि आप एक छोटे से आलसी हैं$newId = exec('uuidgen -r');
JorgeGarza

जवाबों:


282

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 )
    );
}

43
इस समारोह होगा डुप्लिकेट बनाने, तो यह से बचने के लिए जब आप अनन्य मानों की जरूरत है। ध्यान दें कि mt_rand () हमेशा समान संख्या में दिए गए यादृच्छिक संख्याओं के समान अनुक्रम का उत्पादन करेगा। इसलिए हर बार एक बीज दोहराया जाता है, वही सटीक UUID उत्पन्न होता है। इसके आस-पास जाने के लिए, आपको समय और मैक पते का उपयोग करके इसे बोना होगा, लेकिन मुझे यकीन नहीं है कि आप यह कैसे करेंगे, क्योंकि mt_srand () को एक पूर्णांक की आवश्यकता होती है।
पावेल प्रेडिक

12
@PavlePredic mt_srand (crc32 (क्रमबद्ध करें ([microtime (true), 'USER_IP', 'ETC']))); (मैं एक और
विलीम

13
PHP डॉक्स स्पष्ट रूप से चेतावनी देते हैं कि mt_rand () क्रिप्टोग्राफिक रूप से सुरक्षित मान उत्पन्न नहीं करता है। दूसरे शब्दों में, इस फ़ंक्शन द्वारा उत्पन्न मूल्य अनुमानित हो सकते हैं। यदि आपको यह सुनिश्चित करने की आवश्यकता है कि UUIDs पूर्वानुमान योग्य नहीं हैं, तो आपको नीचे दिए गए जैक के समाधान का उपयोग करना चाहिए, जो खुलता है_sandom_pseudo_bytes () फ़ंक्शन का उपयोग करता है।
रिचर्ड केलर

7
यदि आप हर क्षेत्र को कचरे से भरते हैं तो पृथ्वी पर UUID उत्पन्न करने का क्या मतलब है?
ईवे

1
PHP 7.0+ फ़ंक्शन को random_bytes () को परिभाषित करता है जो हमेशा क्रिप्टोग्राफिक रूप से सुरक्षित रैंडम बाइट्स उत्पन्न करेगा या नहीं होने पर अपवाद को फेंक देगा। यह भी Opensl_random_psuedo_bytes () से बेहतर है, जिसका आउटपुट कभी-कभी इन परिस्थितियों में क्रिप्टोग्राफिक रूप से सुरक्षित नहीं होता है।
थोमसट्रेटर

365

इसे अलग-अलग क्षेत्रों में तोड़ने के बजाय, डेटा के यादृच्छिक ब्लॉक को उत्पन्न करना और अलग-अलग बाइट की स्थिति को बदलना आसान है। आपको mt_rand () की तुलना में एक बेहतर यादृच्छिक संख्या जनरेटर का उपयोग करना चाहिए।

RFC 4122 - धारा 4.4 के अनुसार , आपको इन क्षेत्रों को बदलने की आवश्यकता है:

  1. time_hi_and_version (7 वें ऑक्टेट के बिट्स 4-7),
  2. clock_seq_hi_and_reserved (9 वें ऑक्टेट के बिट 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);
    // ...
}

9
* निक्स उपयोगकर्ताओं के लिए एक वैकल्पिक विकल्प है, जिनके पास $data = file_get_contents('/dev/urandom', NULL, NULL, 0, 16);
ओपनसेल

5
इसके अलावा, मैं OpenSSL को mt_rand से बहुत अधिक भरोसा करूंगा।
प्रो। फॉकन

3
@BrunoAugusto यह यादृच्छिक है, और यह डुप्लिकेट प्राप्त करने के लिए (एक अच्छे यादृच्छिक स्रोत के साथ) बहुत ही संभावना नहीं है, लेकिन डेटाबेस स्तर पर इसे लागू करने के लिए एक अच्छा अभ्यास है।
जेक

9
क्या कोई कारण है कि randomvbytes (16) कॉल को गाइडव 4 फंक्शन के अंदर न डालें और इस तरह से गाइडव 4 को कोई भी पैरामीटर पास नहीं करना है?
स्टीफन आर

7
छोटा सुधार: $ डेटा के लिए एक पूर्ण डिफ़ॉल्ट सेट करें, और फिर फ़ंक्शन की पहली पंक्ति यह है: $data = $data ?? random_bytes( 16 ); अब आप अपने खुद के यादृच्छिक डेटा स्रोत को निर्दिष्ट कर सकते हैं, या फ़ंक्शन को आपके लिए करने दें। :-)
स्टीफन आर

118

संगीतकार निर्भरता का उपयोग करने वाला कोई भी व्यक्ति , आप इस लाइब्रेरी पर विचार करना चाह सकते हैं: https://github.com/ramsey/uuid

यह इससे आसान नहीं है:

Uuid::uuid4();

32
ओह, मुझे नहीं पता .... कोड की पांच लाइनें बनाम निर्भरता वाली लाइब्रेरी लोड करना? मैं जैक के फंक्शन को पसंद करता हूं। YMMV
स्टीफन आर

7
स्टीफन को +1। रैमसे uuid में uuid4 की तुलना में बहुत अधिक कार्यक्षमता है। मैं एक केला नहीं चाहता!, यहाँ आपके पास पूरा जंगल है!
lcjury

26
UUID बस यादृच्छिक तार नहीं हैं। यह कैसे काम करता है, इस बारे में एक युक्ति है। एक उचित यादृच्छिक UUID उत्पन्न करने के लिए जिसे मुझे बाद में खारिज करने के बारे में चिंता करने की आवश्यकता नहीं है, मैं अपने स्वयं के कार्यान्वयन की तुलना में एक परीक्षण पुस्तकालय का उपयोग करूंगा।
ब्रेंडन

3
यह एक UUIDv4 है। यह (ज्यादातर, लेकिन कुछ बिट्स के लिए) यादृच्छिक है। यह क्रिप्टोग्राफी नहीं है। "अपना खुद का रोल करने" के खिलाफ व्यामोह मूर्खतापूर्ण है।
गॉर्डन

23

यूनिक्स सिस्टम पर, आपके लिए एक यूआईडी बनाने के लिए सिस्टम कर्नेल का उपयोग करें।

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

क्रेडिट समरन https://serverfault.com/a/529319/210994 पर

नोट !: इस विधि का उपयोग करने के लिए एक uuid वास्तव में एन्ट्रापी पूल को समाप्त करता है, बहुत जल्दी! मैं इसका उपयोग करने से बचूंगा जहां इसे अक्सर कहा जाएगा।


2
पोर्टेबिलिटी के अलावा, ध्यान दें कि यादृच्छिक स्रोत /dev/randomजो ब्लॉक है अगर एंट्रॉपी पूल समाप्त हो गया है।
जेक

@ जैक क्या आप कृपया यूनिक्स सिस्टम पर एन्ट्रापी पूल थकावट के विषय पर कुछ दस्तावेज जोड़ेंगे? मैं एक यथार्थवादी उपयोग के मामले के बारे में अधिक जानना चाहूंगा जहां यह विधि टूट जाती है।
थोरसुमोनर

मुझे इस विशेष कर्नेल फ़ाइल स्रोत से जानकारी प्राप्त करने में असमर्थ था /dev/urandom, जिसमें मेरी समझ से निकास नहीं होगा, लेकिन डुप्लिकेट uuids को वापस करने वाले जोखिम। मुझे लगता है कि यह एक व्यापार है; क्या आपको वास्तव में सिस्टम एन्ट्रापी से प्रभावित एक अद्वितीय आईडी की आवश्यकता है?
थोरसुमोनर

13

V4 uuid बनाने की मेरी खोज में, मैं इस पृष्ठ पर पहले आया, फिर 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

संपादित करें: स्पष्ट करने के लिए, यह फ़ंक्शन आपको हमेशा एक v4 uuid (PHP> = 5.3.0) देगा।

जब com_create_guid फ़ंक्शन उपलब्ध होता है (आमतौर पर केवल विंडोज पर), तो वह इसका उपयोग करेगा और घुंघराले ब्रेसिज़ को पट्टी करेगा।

यदि (लिनक्स) मौजूद नहीं है, तो यह इस मजबूत रैंडम ओपनस्लैट_लगैंडम_पेसूडो_बाइट्स फंक्शन पर वापस आ जाएगा, फिर यह वी 4 यूआईडी में फॉर्मेट करने के लिए vsprintf का उपयोग करेगा।


5

मेरा जवाब टिप्पणी uniqid उपयोगकर्ता टिप्पणी पर आधारित है, लेकिन यह से रीडिंग के बजाय यादृच्छिक स्ट्रिंग उत्पन्न करने के लिए खुलता हैlsl_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

5

यदि आप उपयोग CakePHPकरते हैं तो आप RFC4122 uuid उत्पन्न करने के CakeText::uuid();लिए केकटेक्स्ट क्लास से उनकी विधि का उपयोग कर सकते हैं ।


5

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));
}

4

से प्रेरित होकर broofa के जवाब यहाँ

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');

1
यदि आप अन्य उत्तरों में टिप्पणियों को देखते हैं, तो आप कहेंगे कि लोगों को mt_rand()यादृच्छिकता की गारंटी नहीं है।
डैनियल चेउंग

3

ठीक उसी चीज़ की खोज करने और लगभग खुद इस के एक संस्करण को लागू करने के बाद, मैंने सोचा कि यह ध्यान देने योग्य है कि, यदि आप एक वर्डप्रेस फ्रेमवर्क के भीतर ऐसा कर रहे हैं, तो WP के पास इसके लिए अपना सुपर-सुपर फ़ंक्शन है:

$myUUID = wp_generate_uuid4();

आप विवरण और स्रोत यहां पढ़ सकते हैं ।


1
WP फ़ंक्शन विशेष रूप से mt_rand का उपयोग करता है। तो पर्याप्त अनियमितता नहीं हो सकता
हर्बर्ट पीटर्स

@HerbertPeters तुम सही हो। मैंने केवल इसका उल्लेख किया है क्योंकि यह वन-लाइनर है। मैं यह कहने जा रहा था कि यह साफ-सुथरा होगा यदि उन्होंने इसके लिए कोई फ़िल्टर जोड़ा है तो आप अधिक सुरक्षित / गारंटीड-रैंडम नंबर वापस कर सकते हैं; लेकिन इसके बारे में कहा जाता है कि यदि आप इतने इच्छुक थे, तो आप भी false🤷
indextwo

2

कैसे आप के लिए uuid उत्पन्न करने के लिए mysql का उपयोग करने के बारे में?

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

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

2
MySQL का UUID()फ़ंक्शन v1 uuids बनाता है।
स्टेटिक्सन

2
$uuid = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));

2
कृपया दूसरों को समझने में मदद करने के लिए अपने कोड में एक स्पष्टीकरण जोड़ें।
केफोबार

- यह है कि क्या वास्तव में Symfony polyfil द्वारा किया जाता है github.com/symfony/polyfill-uuid/blob/master/Uuid.php#L320
Serhii पोलिश्चुक

1

टॉम से, 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])

3
यदि वे यूनिक्स या लिनक्स / जीएनयू नहीं चला रहे हैं तो क्या होगा? यह कोड काम नहीं करेगा।
कोल जॉनसन

4
यह भी बहुत धीमी गति से चलने की क्षमता है अगर / dev / random खाली है और पुनः लोड होने के लिए और अधिक एन्ट्रापी की प्रतीक्षा कर रहा है।
ओब्सीडियनएक्स

1
/dev/urandomठीक /dev/randomहोना चाहिए - केवल दीर्घकालिक क्रिप्टोग्राफ़िक कुंजियों की पीढ़ी के लिए उपयोग किया जाना चाहिए।
इरिडैन

उस आधार पर, मैं के साथ आया था इस - यह बोने के लिए गिरावट-बैक के रूप में अनियमितता के कई संभावित स्रोतों, और रिसॉर्ट का उपयोग करता mt_rand()है, तो कुछ भी नहीं है अधिक सजावटी उपलब्ध है।
mindplay.dk

1
अब तक, बस random_bytes()PHP 7 में उपयोग करें और आप से दूर :-)
mindplay.dk

1

मुझे यकीन है कि बाइनरी से दशमलव के लिए 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))
    );

0

सिम्फनी पॉलिफ़िल / यूआईडी का उपयोग करें
तब आप मूल php फ़ंक्शन के रूप में बस यूआईडी उत्पन्न कर सकते हैं:

$uuid = uuid_create(UUID_TYPE_RANDOM);

इसके बारे में, आधिकारिक सिम्फनी ब्लॉप पोस्ट में पढ़ें - https://symfony.com/blog/introducing-the-new-symfony-uuid-polyfill

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.