My team is building a raffle application where the RNG (random number generator) must be truly random so that it can be approved by the Secretary of State to run online raffles.
$winner = $raffle->entries()->inRandomOrder()->first();
$winning_user = $winner->user()->first();
This is how the code has been implemented and I just wanted to see if anyone could give feedback as to how "truly random" this is, or if we should be approaching this in a different way.
Thanks in advance!
The function inRandomOrder
is defined in Illuminate\Database\Query\Builder
class like so
/**
* Put the query's results in random order.
*
* @param string $seed
* @return $this
*/
public function inRandomOrder($seed = '')
{
return $this->orderByRaw($this->grammar->compileRandom($seed));
}
So it just orders by a row that is compileRandom
which is defined in Illuminate\Database\Query\Grammars\Grammar
/**
* Compile the random statement into SQL.
*
* @param string $seed
* @return string
*/
public function compileRandom($seed)
{
return 'RANDOM()';
}
So this is just an SQL statement on LIMITED DATASET ordered randomly
If $raffle->entries()->count()
is 1 then it's 1/1 (100%) probability chance of getting the same value next round, if 50 then 1/50 and so on, you can't trust it not to return the same value (tho unlikely for huge datasets)
for example
App\User::inRandomOrder()->toSql();
Simply results in
select * from `users` order by RAND()
So it's not really up to Laravel, it's up to the SQL engine you're using (MySQL or Postgres...etc)
For MySQL here's what they say
RAND() is not meant to be a perfect random generator. It is a fast way to generate random numbers on demand that is portable between platforms for the same MySQL version.
So you can't trust it to be truly random
If you want a really random number or string with a low chance of duplicating, I would recommend trying an md5
or even better a bcrypt
hash.