Laravel-красноречивый или беглый случайный ряд
Как я могу выбрать случайную строку, используя Eloquent или Fluent в Laravel framework?
Я знаю, что с помощью SQL, вы можете сделать заказ по RAND(). Однако, я хотел бы получить случайную строку без выполнение подсчета количества записей до первоначального запроса.
какие идеи?
10 ответов:
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();
Регистрация в этой статье на случайных строках MySQL. Laravel 5.2 поддерживает это, для более старой версии, нет лучшего решения, чем использование необработанные запросы.
edit 1: как упоминалось Double Gras, orderBy() не позволяет ничего другого, кроме ASC или DESC так как этой изменить. Я обновил свой ответ соответственно.
edit 2: что Laravel 5.2, наконец, реализует функции-оболочки для этого. Это называется inRandomOrder ().
это работает нормально,
$model=Model::all()->random(1);
вы также можете изменить аргумент в случайной функции, чтобы получить более одной записи.
Примечание: не рекомендуется, если у вас есть огромные данные, как это будет получать все строки, а затем возвращает случайное значение.
tl; dr: в настоящее время он реализован в Laravel, см. "edit 3" ниже.
к сожалению, на сегодняшний день есть некоторые предостережения с
->orderBy(DB::raw('RAND()'))
предлагаемое решение:
- это не ДБ-агностик. например, SQLite и PostgreSQL используют
RANDOM()
еще хуже, это решение не применимо, так этот изменить:
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
edit: теперь вы можете использовать orderByRaw () способ:->orderByRaw('RAND()')
. Однако это все еще не ДБ-агностик.FWIW, CodeIgniter реализует специальный
RANDOM
направление сортировки, которое заменяется правильной грамматике при построении запроса. Также это, кажется, довольно легко осуществить. Похоже, у нас есть кандидат на улучшение Laravel:)обновление: вот это вопрос об этом на GitHub, и мое ожидание pull-запрос.
edit 2: давайте прекратим погоню. Начиная с Laravel 5.1.18 вы можете добавить макросы в построитель запросов: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]); });
использование:
User::where('active', 1)->orderByRandom()->limit(10)->get(); DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();
edit 3: наконец-то! Начиная С Laravel 5.2.33 (изменений,PR #13642) вы можете использовать собственный методinRandomOrder()
:User::where('active', 1)->inRandomOrder()->limit(10)->get(); DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
на Laravel 4 и 5 the
order_by
заменить наorderBy
Итак, должно быть:
User::orderBy(DB::raw('RAND()'))->get();
вы также можете использовать метод order_by с свободно и красноречиво, как:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
Это немного странно, но работает.
Edit: как сказал @Alex, это использование чище, а также работает:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
Для Laravel 5.2 >=
используйте красноречивый метод:
inRandomOrder()
метод inRandomOrder может использоваться для случайной сортировки результатов запроса. Например, вы можете использовать этот метод для извлечения случайного пользователя:
$randomUser = DB::table('users') ->inRandomOrder() ->first();
из документов: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
в вашей модели добавить это:
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; }
затем на маршрут/контроллер
$data = YourModel::randomize(8)->get();
появилась
whereRaw('RAND()')
Что делает то же самое, u может затем цепь->get()
или->first()
или даже сойти с ума и добавить->paginate(int)
У меня есть таблица с тысячами записей, так что мне нужно что-то быстро. Это мой код для псевдослучайной строки:
// 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();