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?

152
demandé sur Auromius 0000-00-00 00:00:00

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 () .

390
répondu aebersold 2016-08-08 18:10:57

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.

39
répondu manish 2016-06-14 14:35:50

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();
22
répondu Gras Double 2018-07-02 03:03:12

dans Laravel 4 et 5 le order_by est remplacé par orderBy

ainsi, il devrait être:

User::orderBy(DB::raw('RAND()'))->get();
15
répondu Teodor Talov 2016-06-25 19:48:21

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()'));
8
répondu Bilal Gultekin 2013-03-23 21:20:08

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

6
répondu Manuel Azar 2016-07-14 16:56:18

vous pouvez utiliser:

ModelName::inRandomOrder()->first();
6
répondu simhumileco 2018-07-24 13:37:14

à 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();
2
répondu Neto 2015-07-14 01:21:24

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)

1
répondu ctf0 2014-12-16 09:12:47

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(); 
1
répondu Doc 2016-06-24 08:14:52