Wybierz Ostatni wiersz w tabeli


163

Chciałbym odzyskać ostatni plik wstawiony do mojej tabeli. Wiem, że metoda first()istnieje i udostępnia pierwszy plik w tabeli, ale nie wiem, jak uzyskać ostatnią wstawkę.


Zobacz także stackoverflow.com/questions/33321447/… Jak posortować istniejący związek (hasMany)
Tarek Adam

To jest dla każdego, kto pyta i odpowiada na temat Laravel. Pamiętaj, że ważne jest, aby określić, o której wersji Laravela mówisz. Ogólnie wersje 4 i 5 mają różnice i starsze wersje.
Heroselohim

Odpowiedzi:


224

Będziesz musiał zamawiać według tego samego pola, które składasz do tej pory, ale malejąco. Na przykład, jeśli masz sygnaturę czasową, kiedy wysyłanie zostało wywołane upload_time, zrobiłbyś coś takiego;

Dla wersji Pre-Laravel 4

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

Dla Laravel 4 i nowszych

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

Dla Laravel 5.7 i nowszych

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

Spowoduje to uporządkowanie wierszy w tabeli plików według czasu przesyłania, kolejności malejącej i wybranie pierwszego. Będzie to najnowszy przesłany plik.


15
W przypadku Laravel 4 powinno to być orderBy, a nieorder_by
Jared Eitnier

9
Kiedy używasz ORM, jest to właściwy sposób:User::orderby('created_at', 'desc')->first();
Cas Bloem

1
Laravel 5.x =orderBy('created_at', 'desc')
0x1ad2

9
Dlaczego używasz kolumny created_at? Znacznie szybsze użycie identyfikatora klucza podstawowego. Laravel 5.x Files::orderBy(id', 'desc')->first();Sortuj według daty działa dłużej, ponieważ data jest ciągiem i najprawdopodobniej nie jest indeksowana. Podczas gdy klucz podstawowy jest indeksowany i działa bardzo szybko. Nawet jeśli utworzony_at jest indeksowany, jest to indeksowany ciąg, a nie INT w przypadku podstawowego. Ciąg indeksu ma mniejszą wydajność.
KorbenDallas

4
Komentarz @KorbenDallas powinien być odpowiedzią, ponieważ czasami orderBy('created_at', 'desc')nie podaje ostatniego wiersza. Przykład: 3 wiersze mogą mieć dokładnie tę samą wartość TIMESTAMP, a wraz z orderBy('created_at', 'desc')tobą otrzymasz pierwszy z 3 (który niekoniecznie jest ostatnim wierszem)
viery365

111

Użyj najnowszej lunety dostarczonej przez Laravel po wyjęciu z pudełka.

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

W ten sposób nie odzyskasz wszystkich rekordów. Ładniejszy skrót do zamawiania według.


7
Zwróć uwagę, że ta metoda korzysta z automatycznie generowanej created_atkolumny ($timestamps = true)w modelu, ale można ją wyłączyć na życzenie, aby wystąpił błąd, jeśli nie zostanie zdefiniowany
Plotisateur,

Używam Laravel 5.7 i próbuję zrobić to na Modelu, ale wciąż pobiera wszystkie rekordy dla mnie.
CJ Dennis,

1
Zauważ, że jeśli masz wiele rekordów dodanych w tej samej sekundzie, czas created_at będzie taki sam dla tych rekordów i dlatego rekord zwrócony przez latest () może nie być rekordem, którego się spodziewasz.
F3CP

Pamiętaj, że nie potrzebujesz kolumny „created_at”. Możesz określić, z której kolumny chcesz mieć najnowsze. Na przykład: Model :: latest ('dateColumn') -> first ();
Tom

Może to nie uzyskać rzeczywistego ostatniego wiersza, jeśli dwa wiersze zostaną wstawione w ciągu 1 sekundy (faktycznie spowodowało problemy w testowaniu jednostkowym).
chili

75

Nigdy nie wspomniałeś, czy używasz Eloquent, domyślnego ORM Laravela, czy nie. Jeśli tak, powiedzmy, że chcesz uzyskać najnowszy wpis w tabeli User, przez created_at, prawdopodobnie możesz wykonać następujące czynności:

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

Najpierw porządkuje użytkowników według pola created_at, malejąco, a następnie pobiera pierwszy rekord wyniku.

To zwróci instancję obiektu użytkownika, a nie kolekcję. Oczywiście, aby skorzystać z tej alternatywy, trzeba mieć model User, rozszerzający klasę Eloquent. Może się to wydawać nieco zagmatwane, ale bardzo łatwo jest zacząć, a ORM może być naprawdę pomocny.

Aby uzyskać więcej informacji, zapoznaj się z oficjalną dokumentacją, która jest dość bogata i szczegółowa.


42

Aby poznać szczegóły ostatniego rekordu

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

Aby uzyskać identyfikator ostatniego rekordu

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

14

Kolekcje Laravel mają metodę ostatnią

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

To najlepszy sposób na zrobienie tego.


16
Chciałem tylko zaznaczyć, że all()metoda faktycznie ładuje wszystkie elementy. To nie zadziała w przypadku tabeli z milionami rekordów.
Steven Jeffries

1
Oprócz komentarza Stevena Jeffriesa chciałbym zwrócić uwagę, że wywołanie last()zwraca pojedynczą instancję Eloquent, a nie Collection, a wywołanie pluck()tego jest równoznaczne z wywołaniem Model::all()->pluck('name'), a zatem zwróceniem nameatrybutu wszystkich wierszy w tabeli
ivcandela

5
Ta metoda jest faktycznie gorsza. Pobierasz ostatni plik raw używając wykonania PHP zamiast robić to na poziomie bazy danych. A co, jeśli stół ma miliony surowca, to wiesz, jak bardzo może być nieefektywny?
Bhaskar Dabhi

To najlepszy sposób na zrobienie tego. - Nie! Nigdy nie było i nigdy nie będzie. Ładowałbyś wszystkie wiersze zamiast tylko tego, którego potrzebujesz.
René Roth

11

Spróbuj tego :

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

1
Spowoduje to zwrócenie wielu wierszy. Potrzebuje jednego rzędu. first () pomoże mu z klauzulą ​​orderBy ().
Tahir Afridi

Może to nie uzyskać rzeczywistego ostatniego wiersza, jeśli dwa wiersze zostaną wstawione w ciągu 1 sekundy (faktycznie spowodowało problemy w testowaniu jednostkowym).
chili

1
W przypadku dużej tabeli spowoduje to wyjątek braku pamięci, ponieważ jak wspomniał @TahirAfridi, spowoduje to załadowanie wszystkich wierszy do pamięci.
Rihards

6

Możesz użyć najnowszego zakresu dostarczonego przez Laravel z polem, które chcesz filtrować, powiedzmy, że zostanie uporządkowane według identyfikatora, a następnie:

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

W ten sposób możesz uniknąć zamawiania według created_atpola domyślnie w Laravel.


5

Aby uzyskać szczegóły ostatniego rekordu, użyj poniższego kodu:

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

Nie używaj tego. Jest to bardzo zła praktyka. Jest to zakres latest (), który zapewnia bezpośredni dostęp do ostatnio wstawionego wiersza.
Working Pig

3

Kolejny fantazyjny sposób na zrobienie tego w Laravel 6.x (niepewny, ale musi działać również dla 5.x):

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

Możesz również uzyskać dostęp do pól:

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


Działa również dla mnie w Laravel 5.8, właśnie opublikowałem odpowiedź, zanim zobaczyłem twoją
Dazzle

1
Małe wyjaśnienie, w jaki sposób Laravel robi to za kulisami i dlaczego jest to niebezpieczne dla dużego zestawu danych, get()metoda pobierze wszystko z your_tablei wygeneruje kolekcję, a last()metoda uzyska ostatni element z tej kolekcji. Więc będziesz mieć już wszystkie dane z tabeli załadowane do twojej pamięci (źle). Powinieneś po prostu użyć `DB :: table ('items') -> latest () -> first ();` za sceną wykona polecenie `orderBy ($ column, 'desc')` i pobierz pierwszy rekord.
Anuj Shrestha


1

Jeśli szukasz rzeczywistego wiersza, który właśnie wstawiłeś za pomocą Laravel 3 i 4 podczas wykonywania akcji savelub createna nowym modelu, na przykład:

$user->save();

-lub-

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

następnie wstawiona instancja modelu zostanie zwrócona i może być użyta do dalszych działań, takich jak przekierowanie do strony profilu właśnie utworzonego użytkownika.

Wyszukiwanie ostatniego wstawionego rekordu działa na systemie o małej objętości, ale będzie działać prawie przez cały czas, ale jeśli kiedykolwiek będziesz musiał wstawiać wstawki w tym samym czasie, możesz zakończyć wyszukiwanie w celu znalezienia niewłaściwego rekordu. Może to naprawdę stać się problemem w systemie transakcyjnym, w którym wiele tabel wymaga aktualizacji.


1

W jakiś sposób wszystkie powyższe nie działają dla mnie w Laravel 5.3, więc rozwiązałem swój własny problem za pomocą:

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

mam nadzieję, że uda mi się kogoś wykupić.


1

Użycie Model::where('user_id', $user_id)->latest()->get()->first(); go zwróci tylko jeden rekord, jeśli nie znajdzie, zwróci null. Mam nadzieję, że to pomoże.


0

Jeśli tabela ma pole daty User::orderBy('created_at', 'desc')->first();, myślę, że to ( ) jest najlepszym rozwiązaniem. Ale nie ma pola daty Model ::orderBy('id', 'desc')->first()->id;, jestem pewien, że jest to najlepsze rozwiązanie.


0

należy pamiętać, że last(), latest()nie są deterministyczne, jeśli szukasz kolejnego lub zdarzenia / zamówionej rekordu. Ostatnie / ostatnie rekordy mogą mieć dokładnie tę samą created_atsygnaturę czasową, a to, co otrzymujesz, nie jest deterministyczne. Więc zrób orderBy(id|foo)->first(). Inne pomysły / sugestie, jak być deterministycznym, są mile widziane.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.