Laravel - Éloquent ou Fluide aléatoire ligne
Comment puis-je sélectionner une rangée aléatoire en utilisant éloquent ou couramment Laravel framework?
je sais qu'en utilisant SQL, vous pouvez commander par RAND(). Cependant, je voudrais obtenir la ligne aléatoire sans en faisant un compte sur le nombre d'enregistrements avant la requête initiale.
des idées?
10 réponses
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érifier cet article sur MySQL lignes aléatoires. Laravel 5.2 supporte cela, pour la version plus ancienne, il n'y a pas de meilleure solution que d'utiliser requêtes brutes .
edit 1: Comme indiqué par la Double Gras, orderBy() ne permet pas autre chose alors ASC ou DESC depuis ce du changement. J'ai mis à jour ma réponse en conséquence.
edit 2: Laravel 5.2 finalement implémente une fonction d'enrubannage pour cela. Il s'appelle inRandomOrder () .
Cela fonctionne bien,
$model=Model::all()->random(1);
, vous pouvez aussi changer d'argument dans la fonction aléatoire pour obtenir plus d'un enregistrement.
Note: non recommandé si vous avez des données énormes car cela va d'abord récupérer toutes les lignes et retourne ensuite la valeur aléatoire.
tl;dr: il est aujourd'hui mis en œuvre dans Laravel, voir "edit 3" ci-dessous.
malheureusement, à partir d'aujourd'hui, il ya quelques mises en garde avec la ->orderBy(DB::raw('RAND()'))
solution proposée:
- Il n'est pas DB-agnostique. par exemple Utilisation de SQLite et PostgreSQL
RANDOM()
-
pire encore, cette solution n'est plus applicable depuis ce changement :
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
modifier: Maintenant vous pouvez utiliser le orderByRaw () méthode: ->orderByRaw('RAND()')
. Cependant, ce n'est toujours pas DB-agnostique.
FWIW, CodeIgniter implémente une direction de tri spéciale RANDOM
, qui est remplacée par la grammaire correcte lors de la construction de la requête. Il semble également être assez facile à mettre en œuvre. Regarder comme nous avons un candidat pour améliorer Laravel:)
mise à jour: voici le problème à propos de ce sur GitHub, et mon attente pull request .
edit 2: nous allons couper à la chasse. Depuis Laravel 5.1.18, vous pouvez ajouter des macros au générateur de requêtes:
use Illuminate\Database\Query\Builder;
Builder::macro('orderByRandom', function () {
$randomFunctions = [
'mysql' => 'RAND()',
'pgsql' => 'RANDOM()',
'sqlite' => 'RANDOM()',
'sqlsrv' => 'NEWID()',
];
$driver = $this->getConnection()->getDriverName();
return $this->orderByRaw($randomFunctions[$driver]);
});
Utilisation:
User::where('active', 1)->orderByRandom()->limit(10)->get();
DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();
edit 3: enfin! Depuis Laravel 5.2.33 ( changelog , PR #13642 ), vous pouvez utiliser la méthode native inRandomOrder()
:
User::where('active', 1)->inRandomOrder()->limit(10)->get();
DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
dans Laravel 4 et 5 le order_by
est remplacé par orderBy
ainsi, il devrait être:
User::orderBy(DB::raw('RAND()'))->get();
Vous pouvez également utiliser order_by méthode couramment et éloquent comme:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
C'est un peu bizarre, mais fonctionne.
Edit: comme @Alex a dit, cet usage est plus propre et fonctionne aussi:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
Pour Laravel 5.2 > =
utilisez la méthode éloquente:
inRandomOrder()
la méthode inRandomOrder peut être utilisée pour trier les résultats de la requête au hasard. Par exemple, vous pouvez utiliser cette méthode pour récupérer un utilisateur aléatoire:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
de docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
vous pouvez utiliser:
ModelName::inRandomOrder()->first();
à votre modèle ajouter 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 / controller
$data = YourModel::randomize(8)->get();
il y a aussi whereRaw('RAND()')
qui fait la même chose, u peut alors enchaîner ->get()
ou ->first()
ou même devenir fou et ajouter ->paginate(int)
j'ai une table avec des milliers de disques, donc j'ai besoin de quelque chose rapidement. C'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();