web-dev-qa-db-fra.com

comment obtenir une ligne aléatoire laravel-5

En L-4, c'était simple:

$random_quote = Quotation::all()->random(1);

Mais maintenant, dans L-5, pas une seule méthode décrite dans cet article ne fonctionne: Laravel - Ligne aléatoire éloquente ou courante

Mon fichier de vue devient vide. Des idées?

MODIFIER:

Résolu: $ Random_quote = Quotation :: orderByRaw ("Rand ()") -> first ();

29
Peter

Mise à jour pour Laravel 5.4

Nouveau randomorting in Laravel 5.4->inRandomOrder()->first()

14
Peter

Ces travaux, mais vous n'avez probablement pas utilisé la bonne variable namespace, utilisez simplement l'instruction use située en haut de votre nom class comme ceci:

<?php namespace SomeNamespace;

use App\Quotation; // Says "Quotation.php" is in "App" folder (By default in L-5.0)

class someClass {
    //...
}

Ensuite, vous pouvez utiliser dans votre method quelque chose comme ceci:

// You may add: use DB; at the top to use DB instead of \DB
$random_quote = Quotation::orderBy(\DB::raw('Rand()'))->first();

Ou ca:

$random_quote = Quotation::orderByRaw("Rand()")->first();

Mise à jour (depuis Laravel - 5.2):

$random_quote = Quotation::inRandomOrder()->first();
37
The Alpha

random() donne une erreur en 5.2, vous pouvez donc utiliser inRandomOrderhttps://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset

et cela fonctionne sur Eloquent comme

Model::inRandomOrder()->first()
27
ctf0

OrderByRaw ('Rand ()') a 2 problèmes:

  1. Cela dépend du serveur MySQL
  2. Cela peut être lent sur les grandes tables (va chercher toutes les lignes)

Voici la solution que j'ai utilisée, qui semble être un peu meilleure:

$cnt = $records->count();
if ($cnt == 0)
    return;

$randIndex = Rand(0, $cnt-1);
$obj = $records->skip($randIndex)->take(1)->first();

EDIT: Veuillez noter que ma solution peut être un problème (crash si pas de chance) en cas de demandes parallèles à la base de données, si certains enregistrements sont supprimés entre "count ()" et "skip ()".

12
Benjamin Piette

MISE À JOUR POUR LARAVEL 5.3

J'étais heureux de découvrir qu'il s'agit maintenant d'une fonction de requête native! :RÉ

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

Malheureusement, aucune de ces réponses n’utilise pleinement les collections de Laravel 5. Si vous êtes venu de Google, comme moi, à la recherche d'une solution entièrement native, regardez ci-dessous!

La réponse de The Alpha présente le défaut de dépendance à la base de données et celui de Benjamin, comme il l’a souligné, peut poser problème lorsque des lignes sont supprimées entre les deux. Très improbable, mais toujours possible.

Voici une solution d'une ligne pour sélectionner des lignes aléatoires dans Laravel 5+

// The setup
$numberOfRows = 4;
$models = Model::all(); // or use a ::where()->get();

// And the actual randomisation line
$randRows = $models->shuffle()->slice(0,numberOfRows);

Et voila - codage heureux! Votez quand vous le voyez pour que ça monte sur la page :)

11
Stan Smulders

Je mettrais cela en œuvre un peu différemment, en utilisant l'idée de Benjamin . A Query Scope car cela semble approprié, il est donc réutilisable et il entre dans votre utilisation Eloquent normale.

Remarque:Dans Eloquent 5.2, les portées globales sont intégrées.

Je vais créer un trait que les modèles peuvent utiliser, mais vous pouvez simplement ajouter la méthode scopeRandom directement à votre modèle spécifique.

/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);
    }
}

Ensuite, chaque modèle que vous souhaitez utiliser les étendues globales, nommez-le dans la classe.

/app/Quotation.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Quotation extends Model
{
    use GlobalScopes;

    //...
}

Utilisé:

$randomQuote = \Quotation::random()->first();
8
MetalFrog

Dans Laravel 5.1 (et Laravel 5.2), il existe une méthode random dans la classe Collection renvoyée par le générateur Eloquent.

https://laravel.com/docs/5.1/collections#available-methods

Alors votre appel

$random_quote = Quotation::all()->random(1);

ou

$random_quote = Quotation::where('column', 'value')->get()->random(1);

devrait fonctionner correctement.

3
fsavina

Laravel 5.4 

1) si besoin d'un modèle aléatoire:

$object = Model::all()->random();

2) si besoin de nombreux modèles aléatoires:

$object = Model::all()->random($n); //$n - number of elements
                                    //$object - collection

Commentaire: L'appel de $ collection-> random (1) renverra désormais une nouvelle instance de collection avec un élément. Cette méthode ne renverra qu'un seul objet si aucun argument n'est fourni.

Référence du document: https://laravel.com/docs/5.4/collections#method-random

orderByRaw('Rand()')

Remarque: toutes les lignes du reste de la requête seront prises en compte. Ainsi, si vous avez une grande table sans autres filtres dans la même requête, cela donnera de mauvaises performances, sinon c'est votre option.

1
Luca C.