2014-11-17 3 views
24

В L-4 был прост:как получить случайные строки Laravel-5

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

Но теперь в L-5 не единственный метод, описанный в этой должности работает: Laravel - Eloquent or Fluent random row

Мой вид файл просто пуст. Есть идеи?

EDIT:

Решено: $ random_quote = Котировка :: orderByRaw ("RAND()") -> первый();

+0

Какой код вы пробовали? Это работает, возможно, вы что-то пропустили –

+4

Это, кстати, очень плохой результат. – rmobis

+0

Можете ли вы поделиться по-разному? У меня есть c. 30 000 известных высказываний в базе данных ... – Peter

ответ

33

Этих работ, но, вероятно, вы не использовали право namespace, просто использовать use заявления в верхней части вашего class имени как это:

<?php namespace SomeNamespace; 

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

class someClass { 
    //... 
} 

Затем вы можете использовать в вашем method что-то вроде этого:

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

Или это:

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

Update (С Laravel - 5.2):

$random_quote = Quotation::inRandomOrder()->first(); 
+2

Мы должны поставить first() вместо get() Я печатал строку, и переменная была массивом. Вот почему вид был пустым. – Peter

+0

Добро пожаловать :-) –

+0

'ORDER BY RAND()' на самом деле очень медленный, и я имею в виду действительно, действительно, ... очень медленно. Я начинаю замечать разницу даже на столе с 400 рядами. – orustammanapov

11

orderByRaw ('RAND()') имеет 2 вопроса:

  1. Это зависит от MySQL-сервера
  2. Это может быть медленным на крупных таблицы (извлекает все строки)

Вот решение я использовал, который, кажется, немного лучше:

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

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

EDIT: Обратите внимание, что мое решение может быть проблемой (сбой, если не повезет) в случае запросов parrallel к базе данных, если некоторые записи удаляются между «count()» и «skip()».

10

ОБНОВЛЕНИЕ ДЛЯ Laravel 5,3

Я был рад обнаружить, что это теперь родная функция запроса! : D

Метод inRandomOrder может использоваться для сортировки результатов запроса случайным образом. Например, вы можете использовать этот метод для извлечения случайного пользователя:

$randomUser = DB::table('users') 
      ->inRandomOrder() 
      ->first(); 

К сожалению, ни один из этих ответов не в полной мере использовать Laravel 5'коллекций. Если вы пришли сюда из Google, как и я, ища полностью родное решение, посмотрите ниже!

Ответ от Alpha имеет недостаток зависимости базы данных, и, как он отметил, Бенджамин может создать проблему, когда строки удаляются между ними. Очень маловероятно, но все же возможно.

Вот решение на одну строку, чтобы выбрать случайные строки в 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); 

вуаля - счастливый кодирования! Проголосуйте, когда увидите это, чтобы он поднялся на страницу :)

+4

Хотя это определенно будет работать, чрезмерно получить все результаты таблицы, когда вам нужна только одна строка. Если у вас очень большие таблицы, это значительно снизит производительность. –

+0

Просто используйте a -> take (100)? –

+2

Тогда вы получите только случайную строку из первых 100 строк! –

8

Я бы это немного поменял, используя Benjamin's idea. A Query Scope для этого чувствует себя подходящим, поэтому он многоразовый, и он попадает в ваше обычное «Красноречивое» использование.

Примечание:In Eloquent 5.2, there is built in support for global scopes.

Я собираюсь создать признак, что модели могут использовать, но вы можете просто добавить метод scopeRandom непосредственно к вашей конкретной модели.

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

Затем каждая модель вы хотите использовать глобальные области, имя признака внутри класса.

/app/Quotation.php

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Quotation extends Model 
{ 
    use GlobalScopes; 

    //... 
} 

При использовании:

$randomQuote = \Quotation::random()->first(); 
+1

Умное решение и лучший вариант Laravel Ответьте на эту страницу. – mwallisch

3

В Laravel 5.1 (и Laravel 5.2) существует метод random в Collection класса, возвращенного Благородный строитель.

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

Так ваш звонок

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

или

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

должны работать должным образом.

+3

'$ r = Quotation :: all() -> random (1);' действительно работает, но сначала выполняет 'select * from quotations', который ... может быть довольно медленным, если есть много предложений ... – erapert

1
orderByRaw('RAND()') 

Примечание: Это займет в оперативной памяти всех строк от остальной части запроса, поэтому если у вас есть большой стол Whithout других фильтров в одном запросе он будет давать плохие выступления, в противном случае это ваш вариант

21

random() дает ошибку в 5.2, так что вместо этого вы можете использовать inRandomOrderhttps://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset,

и работает на красноречивые как

Model::inRandomOrder()->first() 
+0

Теперь ** ЭТО ** должен быть принятым ответом. Он не зависит от базы данных и использует возможности инфраструктуры. +1 – mmieluch

0

Laravel 5.4

1) в случае необходимости одна случайная модель:

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

2), если нужно много случайных моделей:

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

Комментарий: Вызов $ галерею-> случайная (1) теперь будет возвращать новый экземпляр коллекции с одним элементом. Этот метод возвращает только один объект, если аргументы не заданы.

Doc ref: https://laravel.com/docs/5.4/collections#method-random

Смежные вопросы