1

I am creating an application at the moment that needs to give the user a unique 8 digit code (numbers only) that they can enter to access restricted parts of my website, think of it as a rudimentary auth, i.e enter the passcode, the passcode matches a user, the user is returned. What I am having trouble with is creating a unique 8 digit code. I know PHP has uniqid() but that returns a string that is too long.

I have thought about creating a hash of time() and the users IP address, but laravel's Hash::create returns integers and chars.

Can anyone point in the direction of creating a random 8 digit code? I have also tried mt_rand but obvioulsy there is the chance that this could create matching digits, unless of course I check the database for the code before saving and re-generate if it exists?

Udders
  • 6,914
  • 24
  • 102
  • 194
  • 1
    Something isn't right about this premise, and 8 digits isn't very unique (even if you had thousands of users, collisions could happen semi-frequently). Why aren't you using standard authorization/authentication methods here? – Tim Biegeleisen Oct 02 '19 at 08:03
  • Also, from a UX perspective, a random 8 digit string may be harder for a user to remember than, say, a few random words or a password that they set for themselves. I think the two point above about auth roles are the way to go :) but if you go ahead with the 8 digits, definitely check the db for duplicates of the uid – party-ring Oct 02 '19 at 08:27
  • plz try this https://hashids.org/php/ – Yaser Darzi Oct 02 '19 at 08:36
  • @YaserDarzi How do you create 8 digit number-only hashes with this? – brombeer Oct 02 '19 at 08:44
  • @kerbholz see this repo https://github.com/amamarul/integer-hashids – Yaser Darzi Oct 02 '19 at 08:54
  • Do you want 8-digit numeric, or do you want alphanumeric? Whichever you choose, depending on random numbers opens you to the chance of generating duplicates. I'd suggest something like https://stackoverflow.com/a/50670084/56778. See the linked blog entry, http://blog.mischel.com/2017/06/20/how-to-generate-random-looking-keys/ – Jim Mischel Oct 02 '19 at 17:12
  • Generating random 8-digit numbers is trivial, but if you use them as IDs, you're likely to run into collisions as your user count gets into the thousands. – Lee Daniel Crocker Oct 02 '19 at 23:42

5 Answers5

1

This is my code to generate random number :

public function generateRandomNumber($length = 8)
{
  $random = "";
  srand((double) microtime() * 1000000);

  $data = "123456123456789071234567890890";
  // $data .= "aBCdefghijklmn123opq45rs67tuv89wxyz"; // if you need alphabatic also

  for ($i = 0; $i < $length; $i++) {
          $random .= substr($data, (rand() % (strlen($data))), 1);
  }

  return $random;

}
Yasin Patel
  • 5,624
  • 8
  • 31
  • 53
  • This looks like it could be useful, is there scenario where 2 outputs could ever be the same? Can you explain the $data string futher is just a list of usable chars to generate the output? – Udders Oct 02 '19 at 13:29
  • $data string futher is just a list of usable chars to generate the output? -> Yes, the character which you need as output – Yasin Patel Oct 02 '19 at 13:30
  • There is very few change of duplication but still if you saving it in Database , you can check it and call it again ( make it recursive function ) – Yasin Patel Oct 02 '19 at 13:32
  • If it's strictly an 8-digit numeric code, there are only 100 million possible codes. After 10,000 codes generated, the likelihood of generating a duplicate is about 50%. I would not suggest using this method. – Jim Mischel Oct 02 '19 at 17:01
1

My suggestion is a do-while loop, this case if the random string already exists it would generate a new one. Generate the code however you want but Laravel actually has a helper (str_random()) to handle this if you wanted.

/**
* Create a unique code
*
* @return string;
*/
if ( ! function_exists('generateUniqueCode')) {
    function generateUniqueCode()
    {
        do {
            $unique_code = str_random(12);
        } while (\App\User::where('code', $unique_code)->count() > 0);


        return $unique_code;
    }
}
Chris Kelker
  • 451
  • 4
  • 4
  • Note: it's `Str::random()` instead of `str_random()` since 5.7 – brombeer Oct 02 '19 at 08:42
  • `str_random()` is a Laravel helper that you can use instead of importing the class. You can use this in all current versions of Laravel – Chris Kelker Oct 03 '19 at 09:04
  • I don't think so, are you 100% sure about this? [Documentation since Laravel 5.7](https://laravel.com/docs/5.7/helpers) says it's `Str:_random()`. – brombeer Oct 03 '19 at 09:31
  • Sorry, perhaps I wasn't being clear. You can use whichever approach suits you best. The helper methods are not deprecated, you can use the helper methods found in `vendor/laravel/framework/src/Illuminate/Support/helpers.php` – Chris Kelker Oct 04 '19 at 11:16
  • Nevermind. You'd need to install the [laravel/helpers](https://github.com/laravel/helpers) package in Laravel 6 to use `str_random()`. There is no function `str_random()` in `vendor/laravel/framework/src/Illuminate/Support/helpers.php` in a plain Laravel 6 installtion. – brombeer Oct 04 '19 at 18:24
0

You need to check-in DB if the number exists or not

$randnum = rand(11111111,99999999);

This will generate a random 8 digit number

Yaser Darzi
  • 1,480
  • 12
  • 24
Rishi1000
  • 344
  • 3
  • 5
0

Try this function For Laravel it will return 8 digit number with check unique in db also.

In Controller Function

$expense_id = Expense::get_random_string();

Modal

public static function get_random_string()
{
    if (function_exists('com_create_guid') === true)
    {
        return trim(com_create_guid(), '{}');
    }
    $random_unique  =  sprintf('%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));

    $expense = Expense::where('expense_id', '=', $random_unique)->first();
    if ($expense != null) {
        $random_unique = $this->get_random_string();
    }
    return $random_unique;
}
Vaibhavi S.
  • 1,083
  • 7
  • 20
0
rand(10000000, 99999999);

You have 1/89999999 chance to fall on the same number, so you can check if it has already been used or not ;)

digitalway
  • 61
  • 7
  • The chance of duplicate is much higher than that. It increases with each number you generate. See https://blog.mischel.com/2017/11/02/birthdays-random-numbers-and-hash-keys/. – Jim Mischel Oct 02 '19 at 17:03