как получить случайную строку laravel-5

В Л-4 было просто:

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

Но теперь в L-5 не работает ни один метод, описанный в этом посте: или Свободная случайная строка

Мой файл просмотра просто становится пустым. Любые идеи?

РЕДАКТИРОВАТЬ:

Решено: $random_quote = Quotation::orderByRaw("RAND()")->first();


person Peter    schedule 17.11.2014    source источник
comment
Какой код вы пробовали? Работает, возможно вы что-то пропустили   -  person The Alpha    schedule 18.11.2014
comment
Кстати, это очень плохо с точки зрения производительности.   -  person rmobis    schedule 18.11.2014
comment
Можете ли вы поделиться способом с точки зрения производительности? у меня с. 30 000 известных высказываний в базе...   -  person Peter    schedule 18.11.2014


Ответы (9)


Это работает, но, вероятно, вы использовали неправильный 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();

Обновление (начиная с Laravel - 5.2):

$random_quote = Quotation::inRandomOrder()->first();
person The Alpha    schedule 17.11.2014
comment
Мы должны поставить first() вместо get(). Я печатал строку, а переменная была массивом. Вот почему вид был пуст. - person Peter; 18.11.2014
comment
ORDER BY RAND() на самом деле очень медленный, и я имею в виду очень, очень, ..., очень медленный. Я начинаю замечать разницу даже на таблице с 400 строками. - person orustammanapov; 18.06.2016
comment
::inRandomOrder() в любом случае разрешает 'ORDER BY RAND()'. - person DJ Far; 01.07.2017
comment
$objects = Model::inRandomOrder()->first(); - самый чистый способ! Спасибо. - person LuizMoratelli; 15.05.2019

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

и он работает на Eloquent как

Model::inRandomOrder()->first()
person ctf0    schedule 16.07.2016
comment
Теперь ЭТО должно быть принятым ответом. Это не зависит от базы данных и использует возможности платформы. +1 - person mmieluch; 02.08.2016

Обновление для Laravel 5.4

Новая случайная сортировка в Laravel 5.4 ->inRandomOrder()->first()

person Peter    schedule 26.02.2017
comment
Это действительно помогло мне, хотя у меня возникла проблема, я хочу, чтобы на странице отображалась только цитата и автор (что и происходит), но также появляется идентификатор, связанный с каждой цитатой, как мне исключить идентификатор? - person PA-GW; 22.05.2019

ОБНОВЛЕНИЕ ДЛЯ ЛАРАВЕЛА 5.3

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

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

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

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

Ответ от The 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);

И вуаля — удачного кодирования! Голосуйте за него, когда увидите его, чтобы он поднялся на странице :)

person Stan Smulders    schedule 14.10.2015
comment
Хотя это определенно сработает, получение всех результатов таблицы, когда вам нужна только одна строка, излишне. Если у вас очень большие таблицы, это значительно снизит производительность. - person Mike Stivala; 21.10.2015
comment
Просто используйте -›take(100)? - person Stan Smulders; 21.10.2015
comment
Тогда вы получите только случайную строку из первых 100 строк! - person Mike Stivala; 22.10.2015
comment
Хорошо, справедливое замечание! Сначала выполните -›count(), а затем сгенерируйте случайное целое число от 1 до $count, а затем используйте его для ::find() — проблема решена, верно? - person Stan Smulders; 22.10.2015
comment
Допустим, у вас есть 500 строк. Вы бы выбрали запись: mt_rand(1,500) и использовали бы find. Цитата::найти(15). Что делать, если строка с идентификатором 15 была удалена? Итак, вы знаете, что у вас есть 500 строк, но вы не знаете, есть ли запись, связанная с каждым идентификатором от 1 до 500. - person MetalFrog; 14.11.2015

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

РЕДАКТИРОВАТЬ: Обратите внимание, что мое решение может быть проблемой (сбой, если не повезет) в случае параллельных запросов к базе данных, если некоторые записи удаляются между «count()» и «skip()».

person Benjamin Piette    schedule 26.08.2015

Я бы реализовал это немного по-другому, используя идею Бенджамина. Область запроса для этого кажется подходящей, поэтому ее можно использовать повторно, и она попадает в ваш нормальное использование Eloquent.

Примечание. В Eloquent 5.2 встроена поддержка глобальных области действия.

Я собираюсь создать трейт, который могут использовать модели, но вы можете просто добавить метод 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();
person MetalFrog    schedule 14.11.2015
comment
Умное решение и лучший ответ для Laravel на этой странице. - person mwallisch; 17.03.2016

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

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

Итак, ваш звонок

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

or

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

должны работать правильно.

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

Ларавель 5.4

1) если нужна одна случайная модель:

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

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

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

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

Ссылка на документ: https://laravel.com/docs/5.4/collections#method-random

person Evgeniy Miroshnichenko    schedule 06.05.2017
comment
Это правильный ответ с моей точки зрения. Другие тоже работают, но даже с Laravel 6.x это задокументированный подход laravel.com/ документы/6.x/коллекции - person s1x; 16.09.2019

orderByRaw('RAND()')

Примечание. Он займет все строки из остальной части запроса, поэтому, если у вас есть большая таблица без других фильтров в том же запросе, это даст плохую производительность, в противном случае это ваш вариант.

person Luca C.    schedule 04.03.2016