Search code examples
phplaravelrandom

Is the laravel method "inRandomOrder()" truly random?


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!


Solution

  • 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.