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


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. 

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


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.


5

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

Model::where('field', 'value')->get()->last()

Не используйте это. Это очень плохая практика, так как есть область last (), которая обеспечивает прямой доступ к последней вставленной строке.
Рабочая свинья

3

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

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

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

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


Также работает для меня в 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'));

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

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


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(). Другие идеи / предложения о том, как быть детерминированным, приветствуются.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.