Comment sélectionner une ligne aléatoire en utilisant Eloquent ou Fluent dans le framework Laravel?
Je sais qu'en utilisant SQL, vous pouvez commander par Rand (). Cependant, j'aimerais obtenir la ligne aléatoire sans / compter le nombre d'enregistrements avant la requête initiale.
Des idées?
Laravel> = 5.2:
User::inRandomOrder()->get();
Laravel 4.2.7 - 5.1:
User::orderByRaw("Rand()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('Rand()'))->get();
Laravel 3:
User::order_by(DB::raw('Rand()'))->get();
Vérifiez cet article sur les lignes aléatoires de MySQL. Laravel 5.2 le supporte. Pour les anciennes versions, il n’existait pas de meilleure solution que d’utiliser RAW Queries .
edit 1: Comme mentionné par Double Gras, orderBy () n'autorise rien d'autre que ASC ou DESC depuis this change. J'ai mis à jour ma réponse en conséquence.
edit 2: Laravel 5.2 implémente enfin une fonction wrapper pour cela. Cela s'appelle inRandomOrder ().
Cela fonctionne très bien,
$model=Model::all()->random(1);
vous pouvez également changer l'argument en fonction aléatoire pour obtenir plus d'un enregistrement.
Remarque: non recommandé si vous avez des données énormes car cela va d'abord récupérer toutes les lignes, puis retourne une valeur aléatoire.
Dans Laravel 4 et 5 le order_by
est remplacé par orderBy
Donc, ça devrait être:
User::orderBy(DB::raw('Rand()'))->get();
Vous pouvez utiliser :
ModelName::inRandomOrder()->first();
Vous pouvez également utiliser la méthode order_by avec fluent et éloquent comme:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('Rand()'));
C'est un peu bizarre, mais ça marche.
Edit: Comme @Alex l’a dit, cette utilisation est plus propre et fonctionne également:
Posts::where_status(1)->order_by(DB::raw('Rand()'));
Pour Laravel 5.2> =
utilisez la méthode Eloquent:
inRandomOrder()
La méthode inRandomOrder peut être utilisée pour trier les résultats de la requête de manière aléatoire. Par exemple, vous pouvez utiliser cette méthode pour récupérer un utilisateur aléatoire:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
from docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
Sur votre modèle, ajoutez ceci:
public function scopeRandomize($query, $limit = 3, $exclude = [])
{
$query = $query->whereRaw('Rand()<(SELECT ((?/COUNT(*))*10) FROM `products`)', [$limit])->orderByRaw('Rand()')->limit($limit);
if (!empty($exclude)) {
$query = $query->whereNotIn('id', $exclude);
}
return $query;
}
puis à route/contrôleur
$data = YourModel::randomize(8)->get();
Il y a aussi whereRaw('Rand()')
qui fait de même, vous pouvez ensuite chaîner ->get()
ou ->first()
ou même devenir fou et ajouter ->paginate(int)
.
J'ai une table avec des milliers d'enregistrements, j'ai donc besoin de quelque chose de rapide. Ceci est mon code pour la ligne pseudo aléatoire:
// count all rows with flag active = 1
$count = MyModel::where('active', '=', '1')->count();
// get random id
$random_id = Rand(1, $count - 1);
// get first record after random id
$data = MyModel::where('active', '=', '1')->where('id', '>', $random_id)->take(1)->first();
Vous pouvez facilement utiliser cette commande:
// Question: nom du modèle
// prend 10 lignes de la base de données dans les enregistrements shuffle.
$questions = Question::orderByRaw('Rand()')->take(10)->get();
Utiliser la fonction Laravel
ModelName::inRandomOrder()->first();