In L-4 it was simple:
$random_quote = Quotation::all()->random(1);
But now in L-5 not a single method described in this post is working: Lar
Update for Laravel 5.4
New randomsorting in Laravel 5.4
->inRandomOrder()->first()
The orderByRaw('RAND()') has 2 issues:
Here is the solution i used, which seems to be a bit better:
$cnt = $records->count();
if ($cnt == 0)
return;
$randIndex = rand(0, $cnt-1);
$obj = $records->skip($randIndex)->take(1)->first();
EDIT: Please note that my solution may be a problem (crash if no luck) in case of parrallel requests to the database, if some records are deleted between the "count()" and the "skip()".
random()
gives error in 5.2, so instead u can use inRandomOrder
https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset ,
and it works on Eloquent like
Model::inRandomOrder()->first()
I'd implement this a little differently, using Benjamin's idea. A Query Scope for this feels appropriate so it's reusable, and it falls into your normal Eloquent use.
Note: In Eloquent 5.2, there is built in support for global scopes.
I'm going to create a trait that models can utilize, but you can just add the scopeRandom
method directly to your specific model.
/app/GlobalScopes.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
trait GlobalScopes
{
public function scopeRandom($query){
$totalRows = static::count() - 1;
$skip = $totalRows > 0 ? mt_rand(0, $totalRows) : 0;
return $query->skip($skip)->take(1);
}
}
Then, each model you want to utilize the global scopes, name the trait inside the class.
/app/Quotation.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Quotation extends Model
{
use GlobalScopes;
//...
}
In use:
$randomQuote = \Quotation::random()->first();
In Laravel 5.1 (and Laravel 5.2) there is a random
method in the Collection
class returned by the Eloquent builder.
https://laravel.com/docs/5.1/collections#available-methods
So your call
$random_quote = Quotation::all()->random(1);
or
$random_quote = Quotation::where('column', 'value')->get()->random(1);
should work properly.
orderByRaw('RAND()')
Note: It will take in ram all the rows from the rest of the query, so if you have a large table whithout other filters in the same query it will give bad performances, otherwise this is your option