How to generate unique random value for each user in laravel and add it to database

71,429

Solution 1

Your logic isn't technically faulty. However, if your application attracts lots of users, fetching all of the random numbers may well become unnecessarily expensive, in terms of resources and computation time.

I would suggest another approach, where you generate a random number and then check it against the database.

function generateBarcodeNumber() {
    $number = mt_rand(1000000000, 9999999999); // better than rand()

    // call the same function if the barcode exists already
    if (barcodeNumberExists($number)) {
        return generateBarcodeNumber();
    }

    // otherwise, it's valid and can be used
    return $number;
}

function barcodeNumberExists($number) {
    // query the database and return a boolean
    // for instance, it might look like this in Laravel
    return User::whereBarcodeNumber($number)->exists();
}

Solution 2

You can use php's uniqid() function to generate a unique ID based on the microtime (current time in microseconds)

Example:

<?php
echo uniqid();
?>

Output:

56c3096338cdb

Solution 3

This is good:

do {
   $refrence_id = mt_rand( 1000000000, 9999999999 );
} while ( DB::table( 'transations' )->where( 'RefrenceID', $refrence_id )->exists() );

Solution 4

To avoid the problem of having to check to see if a matching code exists every time a new one is created, I just catch MySQL's duplicate record exception (error code 1062). If that error is caught, I just call the function again until the save is successful. That way, it only has to generate a new code if it collides with an existing one. Runs a lot faster -- but obviously gets a bit slower as your number of users approaches the number of possible barcodes.

function generateBarcode($user_id) {
    try {
        $user = User::find($user_id);
        $user->barcode = mt_rand(1000000000, 9999999999);
        $user->save();

    } catch (Exception $e) {
        $error_info = $e->errorInfo;
        if($error_info[1] == 1062) {
            generateBarcode($user_id);
        } else {
            // Only logs when an error other than duplicate happens
            Log::error($e);
        }

    }
}

So just loop through all the users you want to assign a code to:

foreach(User::all() as $user) {
    generateBarcode($user->id);
}

You could also add some logic to escape the function loop if a maximum number of attempts are made, but I've never bothered because collisions are unlikely.

Solution 5

One Solution could be like this:

use Illuminate\Support\Facades\Validator;
private function genUserCode(){
    $this->user_code = [
        'user_code' => mt_rand(1000000000,9999999999)
    ];

    $rules = ['user_code' => 'unique:users'];

    $validate = Validator::make($this->user_code, $rules)->passes();

    return $validate ? $this->user_code['user_code'] : $this->genUserCode();
}

Its generating a random number between 1000000000 and 9999999999. After that, it validates the number against the table. If true then it returns the number, otherwise runs the function again.

Share:
71,429

Related videos on Youtube

Nasif Md. Tanjim
Author by

Nasif Md. Tanjim

I am a software developer. I work in Java related technologies including Android. I also have modest skill in frontend technologies.

Updated on September 24, 2020

Comments

  • Nasif Md. Tanjim
    Nasif Md. Tanjim over 3 years

    I am developing a event organization website. Here when the user registers for an event he will be given a unique random number(10 digit), which we use to generate a barcode and mail it to him. Now,

    1. I want to make the number unique for each registered event.
    2. And also random

    One solution is to grab all the random numbers in an array and generate a random number using Php rand(1000000000, 9999999999) and loop through and check all the values. Grab the first value that doesn't equal to any of the values in the array and add it to the database.

    But I am thinking that there might be a better solution to this. Any suggestion?

    • Mark Miller
      Mark Miller about 9 years
      By "unique for each registered event" do you mean that a random number for event A needs to be distinguishable from a random number for event B?
    • Joel Hinz
      Joel Hinz about 9 years
      I didn't think of that interpretation, but it seems logical. If yes, my answer would be easy to modify though.
  • lukasgeiter
    lukasgeiter about 9 years
    It doesn't even have to be the primary key. A UNIQUE index will suffice :)
  • Pavan Jiwnani
    Pavan Jiwnani about 9 years
    @OP are you still looking for any alternate solution?
  • Mladen Janjetovic
    Mladen Janjetovic almost 9 years
    with mt_rand(1000000000, 9999999999) I am getting only numbers that starts with 11..., 10... and 12... That is one strange random function
  • rebellion
    rebellion about 5 years
    This is a really good answer and should be accepted as an answer. However, what does the GeneratorException.php file look like?
  • Sanjay
    Sanjay about 5 years
    @Joel Hinz Always quering against database for uniqueness might be cumbersome . So what abount generating current timestamp and appending it with some other string or random nubmers according to transaction id format.. .:)
  • Joel Hinz
    Joel Hinz about 5 years
    @SanjayKhadka It's a span of 1000000000, 9999999999... unless the database contains millions of products, that isn't going to be a problem. Plus, I was going by OP's specifications.
  • Satish
    Satish almost 4 years
    LIMIT number of loops/iteration of do-while block by using count in WHILE condition blocks otherwise it may took long time/infinite looping if there are large number of entries and range length is short (4-6 for OTP).
  • Diego Vieira
    Diego Vieira over 3 years
    Warning This function does not guarantee uniqueness of return value. Since most systems adjust system clock by NTP or like, system time is changed constantly. Therefore, it is possible that this function does not return unique ID for the process/thread. Use more_entropy to increase likelihood of uniqueness.
  • asela daskon
    asela daskon about 3 years
    in laravel 8 I've got the error "undefine function call". As a solution call the function as below. if( $this->barcodeNumberExists($number)) { }
  • Joel Hinz
    Joel Hinz about 3 years
    @aseladaskon They're just functions. If you put them in a class, you need to use $this-> to call them.
  • Harry
    Harry almost 3 years
    Just a suggestion, using EPOCH time might help. Probably, EPOCH + mt_rand() could be one of the good possibility. So if atall, a DB call is required, we can be sure that it wont exceed more than 1 service call. $number = time() . mt_rand(1000, 999);
  • Masaba James Moses
    Masaba James Moses almost 2 years
    This sorted my problem, Thanks a lot