سؤال

أريد إنشاء معرف فريد ولكن 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);

وقد ترغب أيضا للتأكد من أن الرسائل لا تشكل كلمة في dictionnary. قد يكون من الانجليزية dictionnary كله أو مجرد dictionnary سيئة كلمة لتجنب الأشياء أن العميل يجد من سوء الذوق.

وتحرير: أود أن أضيف أيضا هذا معنى إلا إذا، كما كنت تنوي استخدامها، انها ليست لكمية كبيرة من المواد لأن هذا يمكن الحصول على بطء جدا والمزيد من الاصطدامات تحصل عليه (الحصول على ID بالفعل في الجدول) . وبطبيعة الحال، فأنت تريد جدول مفهرسة وسترغب في قرص عدد من الرسائل في الهوية لتجنب الاصطدام. في هذه الحالة، مع 6 رسائل، وكنت قد 26 ^ 6 = 308915776 معرفات فريدة الممكنة (ناقص كلمات بذيئة) والذي ينبغي أن يكون كافيا لحاجتك 10000.

وتحرير: إذا كنت ترغب في مزيج من الحروف والأرقام التي يمكن استخدام التعليمات البرمجية التالية:

$random .= rand(0, 1) ? rand(0, 9) : chr(rand(ord('a'), ord('z')));

نصائح أخرى

وgen_uuid () من خلال غورد.

وpreg_replace حصلت على بعض UTF-8 قضايا مزعجة، والذي يسبب somtimes المرن لاحتواء "+" أو "/". للالتفاف على هذا، لديك لجعل صراحة نمط 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);
}

نتيجة (أمثلة):

  • cjnp56brdy
  • 9d5uv84zfa
  • ih162lryez
  • ri4ocf6tkj
  • xj04s83egi

وهناك طريقتان للحصول على معرف فريد موثوق: جعله وقتا طويلا والمتغير أن فرص حدوث تصادم صغيرة مذهلة (كما هو الحال مع GUID) أو تخزين جميع معرفات ولدت في جدول للبحث (إما في الذاكرة أو في DB أو ملف) للتحقق من تفرد على جيل واحد.

إذا كنت طالبا حقا كيف يمكنك أن تولد مثل هذا المفتاح القصير وضمان تفرده دون نوع من الاختيار مكررة، فإن الجواب هو، لا يمكنك.

إليك الروتين تستخدم لbase62s عشوائية من أي طول ...

ودعوة gen_uuid() يعود سلاسل مثل WJX0u0jV, E9EMaZ3P الخ.

وافتراضيا هذا يعود 8 أرقام، وبالتالي مساحة 64 ^ 8 أو ما يقرب من 10 ^ 14 هذا غالبا ما يكون كافيا لجعل الاصطدام نادرة جدا.

لسلسلة أكبر أو أصغر، وتمرير في $ ليون كما تريد. لا يوجد حد في الطول، وأنا إلحاق حتى راض [يصل إلى حد سلامة 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 = 100;
base_convert($id, 10, 36);

والحصول على القيمة الأصلية مرة أخرى:

intval($str,36);

لا يمكن اتخاذ الفضل في هذا لأنه هو من الصفحة تجاوز كومة أخرى، ولكن أعتقد أنه كان الحل أنيقة جدا ورهيبة أنه كان يستحق نسخ أكثر لهذا الموضوع للناس الرجوع إلى ذلك.

هل يمكن استخدام رقم وعادل تحويله إلى قاعدة 36 عدد إذا كنت ترغب في تحويله ذهابا وإيابا. ويمكن استخدامها في أي جدول مع معرف صحيح.

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

والناس الذكية يمكن على الأرجح أنها من أصل الرقم مع أمثلة معرف كافية. لا تدع هذا الغموض تحل محل الأمن.

وخطرت لي ما اعتقد هو الحل بارد جدا القيام بذلك دون الاختيار التفرد. اعتقدت أن مشاركة لأي زائر في المستقبل.

وعداد هو وسيلة سهلة حقا لضمان تفرد أو إذا كنت تستخدم قاعدة بيانات مفتاح أساسي يضمن أيضا التفرد. والمشكلة هي أنه يبدو سيئا ووقد تكون عرضة للخطر. فأخذت تسلسل ومختلطة أنه حتى مع الشفرات. منذ الشفرات يمكن عكسها، وأنا أعلم كل هوية هي فريدة من نوعها في حين لا تزال تظهر بشكل عشوائي.

وانها الثعبان ليس بي، ولكن قمت بتحميل الشفرة هنا: 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');
}

ويمكنك أيضا القيام بذلك مثل هذا:

public static function generateCode($length = 6)
    {
        $az = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $azr = rand(0, 51);
        $azs = substr($az, $azr, 10);
        $stamp = hash('sha256', time());
        $mt = hash('sha256', mt_rand(5, 20));
        $alpha = hash('sha256', $azs);
        $hash = str_shuffle($stamp . $mt . $alpha);
        $code = ucfirst(substr($hash, $azr, $length));
        return $code;
    }

يمكنك أن تفعل ذلك دون نجس/costy الاشياء مثل حلقات السلسلة تسلسالت أو عدة مكالمات راند () ، في بيئة نظيفة وسهلة القراءة وسيلة.أيضا, فمن الأفضل استخدام mt_rand():

function createRandomString($length)
{
    $random = mt_rand(0, (1 << ($length << 2)) - 1);
    return dechex($random);
}

إذا كنت بحاجة إلى السلسلة أن يكون طول بالضبط في أي حال, فقط لوحة سداسية مع عدد الأصفار:

function createRandomString($length)
{
    $random = mt_rand(0, (1 << ($length << 2)) - 1);
    $number = dechex($random);
    return str_pad($number, $length, '0', STR_PAD_LEFT);
}

فإن "النظرية backdraw" ، التي تقتصر على PHPs قدرات - ولكن هذا هو أكثر الفلسفي المسألة في هذه الحالة ;) دعنا نذهب من خلال ذلك على أي حال:

  • PHP هي محدودة في ما يمكن أن تمثل عرافة عدد تفعل ذلك من هذا القبيل.هذا من شأنه أن يكون $length <= 8 على الأقل على نظام 32bit, حيث PHPs قيود على هذا ينبغي أن يكون 4.294.967.295 .
  • PHPs مولد رقم عشوائي أيضا أقصى.بالنسبة mt_rand() على الأقل على نظام 32bit ، ينبغي أن يكون 2.147.483.647
  • لذلك كنت نظريا تقتصر على 2.147.483.647 معرفات.

وبالعودة إلى الموضوع - بديهية do { (generate ID) } while { (id is not uniqe) } (insert id) لديها عيب واحد و واحد ممكن الخلل التي قد تدفع لك مباشرة إلى الظلام...

العيب: التحقق هو التشاؤم.تفعل ذلك من هذا القبيل دائما يتطلب التحقق في قاعدة البيانات.وجود ما يكفي من keyspace (على سبيل المثال طول 5 الخاص بك 10k مقالات) سيكون من المستبعد تماما تسبب التصادم في كثير من الأحيان ، كما أنه قد يكون نسبيا أقل الموارد المستهلكة إلى مجرد محاولة لتخزين البيانات ثم أعد المحاولة فقط في حالة وجود مفتاح فريد خطأ.

عيب: المستخدم يسترجع هويته أن يحصل التحقق من أنها لم تتخذ بعد.ثم رمز محاولة لإدراج البيانات.ولكن في هذه الأثناء ، المستخدم ب دخلت نفس الحلقة و للأسف يسترد نفس رقم عشوائي ، لأن المستخدم لا يتم تخزين حتى الآن و هذا الرقم لا يزال مجانا.الآن نظام مخازن إما المستخدم ب أو المستخدم, و عند محاولة تخزين المستخدم الثاني, هناك بالفعل هو الآخر في الوقت نفسه - وجود نفس معرف.

كنت بحاجة إلى التعامل مع هذا الاستثناء في أي حالة تحتاج إلى إعادة محاولة الإدراج مع أنشئت حديثا الهوية.مضيفا هذا في حين الحفاظ على التشاؤم التحقق من حلقة (التي قد تحتاج إلى إعادة إدخال) سيؤدي قبيحة جدا و من الصعب متابعة المدونة. لحسن الحظ الحل هذا هو نفسه مثل واحد العيب: فقط لأنها تذهب في المقام الأول ومحاولة لتخزين البيانات.في حالة فريدة من نوعها مفتاح الخطأ فقط إعادة المحاولة مع الهوية الجديدة.

اتخاذ lookt في هذه المادة

وهذا ما يفسر كيفية توليد قصيرة معرفات فريدة من bdd معرفات مثل يوتيوب لا.

في الواقع وظيفة في هذه المادة هو ذات الصلة جدا وظيفة php base_convert الذي يحول عددا من قاعدة إلى أخرى (ولكن فقط ما يصل الى قاعدة 36).

function rand_str($len = 12, $type = '111', $add = null) {
    $rand = ($type[0] == '1'  ? 'abcdefghijklmnpqrstuvwxyz' : '') .
            ($type[1] == '1'  ? 'ABCDEFGHIJKLMNPQRSTUVWXYZ' : '') .
            ($type[2] == '1'  ? '123456789'                 : '') .
            (strlen($add) > 0 ? $add                        : '');

    if(empty($rand)) $rand = sha1( uniqid(mt_rand(), true) . uniqid( uniqid(mt_rand(), true), true) );

    return substr(str_shuffle( str_repeat($rand, 2) ), 0, $len);
}

إذا كنت تفعل مثل نسخة أطول من استخدام رقم فريد من نوعه هذا:
$ uniqueid = SHA1 (MD5 (الوقت ()))؛

ولكن أفضل جواب: أصغر فريدة من نوعها "تجزئة مثل" سلسلة نظرا فريد ID قاعدة البيانات - PHP الحل ، لا ثالث المكتبات حزب المطلوبة.

وهنا رمز:

<?php
/*
THE FOLLOWING CODE WILL PRINT:
A database_id value of 200 maps to 5K
A database_id value of 1 maps to 1
A database_id value of 1987645 maps to 16LOD
*/
$database_id = 200;
$base36value = dec2string($database_id, 36);
echo "A database_id value of 200 maps to $base36value\n";
$database_id = 1;
$base36value = dec2string($database_id, 36);
echo "A database_id value of 1 maps to $base36value\n";
$database_id = 1987645;
$base36value = dec2string($database_id, 36);
echo "A database_id value of 1987645 maps to $base36value\n";

// HERE'S THE FUNCTION THAT DOES THE HEAVY LIFTING...
function dec2string ($decimal, $base)
// convert a decimal number into a string using $base
{
    //DebugBreak();
   global $error;
   $string = null;

   $base = (int)$base;
   if ($base < 2 | $base > 36 | $base == 10) {
      echo 'BASE must be in the range 2-9 or 11-36';
      exit;
   } // if

   // maximum character string is 36 characters
   $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

   // strip off excess characters (anything beyond $base)
   $charset = substr($charset, 0, $base);

   if (!ereg('(^[0-9]{1,50}$)', trim($decimal))) {
      $error['dec_input'] = 'Value must be a positive integer with < 50 digits';
      return false;
   } // if

   do {
      // get remainder after dividing by BASE
      $remainder = bcmod($decimal, $base);

      $char      = substr($charset, $remainder, 1);   // get CHAR from array
      $string    = "$char$string";                    // prepend to output

      //$decimal   = ($decimal - $remainder) / $base;
      $decimal   = bcdiv(bcsub($decimal, $remainder), $base);

   } while ($decimal > 0);

   return $string;

}

?>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top