Выберите последнюю строку в таблице

163

Я хотел бы получить последний файл, вставленный в мою таблицу. Я знаю, что метод first()существует и предоставляет вам первый файл в таблице, но я не знаю, как получить последнюю вставку.

Карлос Суньол
источник
Также см. Stackoverflow.com/questions/33321447/… Как отсортировать существующие отношения (hasMany)
Тарек Адам
Это для всех, кто спрашивает и отвечает о Laravel. Помните, что важно указать, о какой версии Laravel вы говорите. Обычно версии 4 и 5 имеют отличия и более старые версии тоже.
Героселоим

Ответы:

224

Вам нужно будет упорядочить по тому же полю, которое вы сейчас упорядочиваете, но по убыванию. Например, если у вас есть отметка времени, когда загрузка была завершена upload_time, вы должны сделать что-то вроде этого;

Для Pre-Laravel 4

return DB::table('files')->order_by('upload_time', 'desc')->first();

Для Laravel 4 и далее

return DB::table('files')->orderBy('upload_time', 'desc')->first();

Для Laravel 5.7 и выше

return DB::table('files')->latest('upload_time')->first();

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

Иоахим Исакссон
источник
15
Для Laravel 4 это должно быть orderByне такorder_by
Джаред Эйтньер
9
Когда вы используете ORM, это правильный путь:User::orderby('created_at', 'desc')->first();
Cas Bloem
1
Laravel 5.x =orderBy('created_at', 'desc')
0x1ad2
9
Почему вы используете колонку create_at? Намного быстрее использовать идентификатор первичного ключа. Laravel 5.x Files::orderBy(id', 'desc')->first();Порядок по дате работает дольше, потому что дата строковая и, скорее всего, не проиндексирована. Пока первичный ключ индексируется и работает супер быстро. Даже если созданный индексированный, он является индексированной строкой, а не INT в случае первичного. Индексная строка имеет меньшую производительность.
KorbenDallas
4
@KorbenDallas комментарий должен быть ответом, потому что иногда orderBy('created_at', 'desc')не дает вам последний ряд. Пример: 3 строки могут иметь одно и то же значение TIMESTAMP, и вместе с orderBy('created_at', 'desc')вами вы получите первую из 3 (которая не обязательно является последней строкой)
viery365
111

Используйте новейшие возможности, предоставленные Laravel из коробки.

Model::latest()->first();

Таким образом, вы не получите все записи. Хороший ярлык на заказ.

Ник
источник
7
Обратите внимание, что этот метод использует автоматически сгенерированный created_atстолбец ($timestamps = true)в модели, но может быть отключен по желанию, поэтому у вас будет ошибка, если она не определена
Plotisateur
Я использую Laravel 5.7 и пытаюсь сделать это на модели, которая по-прежнему возвращает все записи для меня.
CJ Деннис
1
Обратите внимание, что если в одну и ту же секунду добавлено несколько записей, время create_at для этих записей будет одинаковым, и поэтому запись, возвращаемая функцией last (), может не соответствовать ожидаемой вами записи.
F3CP
Обратите внимание, что вам не нужен столбец create_at. Вы можете указать, из какого столбца вы хотите последний. Например: Model :: latest ('dateColumn') -> first ();
Том
Это может не дать фактическую последнюю строку, если две строки вставляются в течение 1 секунды (фактически это вызвало проблемы в модульном тестировании).
чили
75

Вы никогда не упоминали, используете ли вы Eloquent, ORM по умолчанию Laravel или нет. В случае, если вы, скажем, хотите получить самую последнюю запись таблицы User, с помощью create_at, вы, вероятно, могли бы сделать следующее:

User::orderBy('created_at', 'desc')->first();

Сначала он упорядочивает пользователей по полю create_at по убыванию, а затем принимает первую запись результата.

Это вернет вам экземпляр объекта User, а не коллекцию. Конечно, чтобы использовать эту альтернативу, вам нужна модель User, расширяющая класс Eloquent. Это может показаться немного запутанным, но это действительно легко начать, и ORM может быть действительно полезным.

Для получения дополнительной информации ознакомьтесь с официальной документацией, которая довольно богата и детальна.

Луис Миланезе
источник
42

Чтобы получить последние детали записи

  1. Model::all()->last(); или
  2. Model::orderBy('id', 'desc')->first();

Чтобы получить последний идентификатор записи

  1. Model::all()->last()->id; или
  2. Model::orderBy('id', 'desc')->first()->id;
Хасина П.А.
источник
14

У коллекции Laravel есть метод last

Model::all() -> last(); // last element 
Model::all() -> last() -> pluck('name'); // extract value from name field. 

Это лучший способ сделать это.

mdamia
источник
16
Просто хотел отметить, что all()метод на самом деле загружает все элементы. Это не будет работать на столе с миллионами записей.
Стивен Джеффрис
1
В дополнение к комментарию Стивена Джеффриса, я хотел бы отметить, что вызов last()возвращает один экземпляр Eloquent, а не коллекцию, и вызов pluck()по нему равен вызову Model::all()->pluck('name'), поэтому возвращается nameатрибут всех строк в таблице
ivcandela
5
Этот метод на самом деле хуже. Вы выбираете последнее сырье, используя выполнение PHP вместо того, чтобы делать это как уровень БД. Что если в таблице миллионы необработанных материалов, то вы знаете, насколько это может быть неэффективно?
Бхаскар Дабхи
Это лучший способ сделать это. - нет! Никогда не был, никогда не буду. Вы будете загружать все строки, а не только ту, которая вам нужна.
Рене Рот
11

Попробуй это :

Model::latest()->get();
Марк-герой
источник
1
Это вернет несколько строк. Ему нужен один ряд. first () поможет ему с предложением orderBy ().
Таир Африди
Это может не дать фактическую последнюю строку, если две строки вставляются в течение 1 секунды (фактически это вызвало проблемы в модульном тестировании).
чили
1
В большой таблице это приведет к исключению нехватки памяти, поскольку, как упомянул @TahirAfridi, это загрузит все строки в память.
Рихардс
6

Вы можете использовать последнюю область, предоставленную Laravel, с полем, которое вы хотите отфильтровать, скажем, оно будет упорядочено по ID, затем:

Model::latest('id')->first();

Таким образом, вы можете избежать упорядочения по created_atполю по умолчанию в Laravel.

tiaguinhow
источник
5

Чтобы получить последние детали записи, используйте код ниже:

Model::where('field', 'value')->get()->last()
Jimuel Palaca
источник
Не используйте это. Это очень плохая практика, так как есть область last (), которая обеспечивает прямой доступ к последней вставленной строке.
Рабочая свинья
3

Еще один интересный способ сделать это в Laravel 6.x (не уверен, но должен работать и для 5.x):

DB::table('your_table')->get()->last();

Вы также можете получить доступ к полям:

DB::table('your_table')->get()->last()->id;

Towelie
источник
Также работает для меня в Laravel 5.8, только что опубликовал ответ, прежде чем увидеть ваш
Dazzle
1
Небольшое объяснение того, как laravel делает это за кулисами и почему это опасно для большого набора данных, get()метод извлекает все из your_tableколлекции и генерирует коллекцию, а last()метод получает последний элемент из этой коллекции. Таким образом, у вас уже есть все данные из таблицы, загруженные в вашу память (плохо). Вы должны просто использовать `DB :: table ('items') -> latest () -> first ();` за сценой он выполняет `orderBy ($ column, 'desc')` и извлекает первую запись.
Анудж Шреста
1

Если вы ищете фактическую строку, которую вы только что вставили с помощью Laravel 3 и 4, когда выполняете действие saveили createдля новой модели, например:

$user->save();

-или-

$user = User::create(array('email' => 'example@gmail.com'));

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

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

bloggidy
источник
1

Почему-то все вышеперечисленное не работает для меня в laravel 5.3, поэтому я решил свою проблему, используя:

Model::where('user_id', '=', $user_id)->orderBy('created_at', 'desc')->get();

надеюсь, смогу выручить кого-то.

Мертвый парень
источник
1

Использование Model::where('user_id', $user_id)->latest()->get()->first(); это вернет только одну запись, если не найти, он вернется null. Надеюсь, это поможет.

风声 猎猎
источник
0

Если в таблице есть поле даты User::orderBy('created_at', 'desc')->first();, я думаю , это ( ) - лучшее решение. Но здесь нет поля даты, Model ::orderBy('id', 'desc')->first()->id;это лучшее решение, я уверен.

Ван Синь
источник
0

иметь в виде , что last(), latest()не являются детерминированным , если вы ищете последовательный или событие / заказанную запись. Последние / последние записи могут иметь одинаковую created_atвременную метку, и возвращаемая вами информация не является детерминированной. Так и делай orderBy(id|foo)->first(). Другие идеи / предложения о том, как быть детерминированным, приветствуются.

mangonights
источник