Seleziona Ultima riga nella tabella


163

Vorrei recuperare l'ultimo file inserito nella mia tabella. So che il metodo first()esiste e ti fornisce il primo file nella tabella ma non so come ottenere l'ultimo inserimento.


Vedi anche stackoverflow.com/questions/33321447/… Come ordinare una relazione esistente (hasMany)
Tarek Adam

Questo è per chiunque chieda e risponda di Laravel. Ricorda che è importante specificare la versione di Laravel di cui stai parlando. Generalmente le versioni 4 e 5 presentano differenze e anche versioni precedenti.
Heroselohim,

Risposte:


224

Dovrai ordinare per lo stesso campo che stai ordinando ormai, ma in ordine decrescente. Ad esempio, se hai un timestamp al termine del caricamento chiamato upload_time, faresti qualcosa del genere;

Per Pre-Laravel 4

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

Per Laravel 4 e successivi

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

Per Laravel 5.7 e versioni successive

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

Ciò ordinerà le righe nella tabella dei file in base al tempo di caricamento, all'ordine decrescente e prenderà la prima. Questo sarà l'ultimo file caricato.


15
Per Laravel 4 questo dovrebbe essere orderBy, nonorder_by
Jared Eitnier,

9
Quando usi ORM, questo è un modo corretto:User::orderby('created_at', 'desc')->first();
Cas Bloem,

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

9
Perché stai usando la colonna Created_at? Molto più veloce per usare l'ID chiave primaria. Laravel 5.x Files::orderBy(id', 'desc')->first();Ordina per data funziona più a lungo perché la data è stringa e molto probabilmente non indicizzata. Mentre la chiave primaria è indicizzata e funziona molto velocemente. Anche se creato_at indicizzato, è stringa indicizzata e non INT in caso di primario. La stringa di indice ha prestazioni inferiori.
KorbenDallas,

4
Il commento di @KorbenDallas dovrebbe essere la risposta perché a volte orderBy('created_at', 'desc')non ti dà l'ultima riga. Esempio: 3 righe possono avere esattamente lo stesso valore TIMESTAMP e con orderBy('created_at', 'desc')te otterrai il primo dei 3 (che non è necessariamente l'ultima riga)
viery365

111

Utilizza immediatamente l'ambito più recente fornito da Laravel.

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

In questo modo non stai recuperando tutti i record. Una scorciatoia più piacevole da ordinare.


7
Si noti che questo metodo utilizza la created_atcolonna generata automaticamente ($timestamps = true)nel modello, ma può essere disabilitato a piacimento, quindi si avrebbe un errore se non definito
Plotisateur

Sto usando Laravel 5.7 e sto provando a farlo su un Modello per cui ancora recupero tutti i record per me.
CJ Dennis,

1
Si noti che se si hanno più record aggiunti nello stesso secondo, il tempo creato_at sarà lo stesso per questi record e quindi il record restituito da latest () potrebbe non essere il record che ci si aspetta che sia.
F3CP,

Nota che non hai bisogno di una colonna "Created_at". È possibile specificare da quale colonna si desidera l'ultimo. Ad esempio: Model :: latest ('dateColumn') -> first ();
Tom

Questo potrebbe non riuscire a ottenere l'ultima riga effettiva se due righe vengono inserite entro 1 secondo (effettivamente causato problemi nel test unitario).
chili

75

Non hai mai menzionato se stai usando Eloquent, l'ORM predefinito di Laravel o meno. In caso affermativo, supponiamo che tu desideri ottenere l'ultima voce di una tabella utente, di Created_at, probabilmente potresti fare come segue:

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

Prima ordina gli utenti in base al campo Created_at, in ordine decrescente, quindi prende il primo record del risultato.

Ciò restituirà un'istanza dell'oggetto Utente, non una raccolta. Naturalmente, per sfruttare questa alternativa, devi avere un modello utente, che estende la classe Eloquent. Questo può sembrare un po 'confuso, ma è davvero facile iniziare e ORM può essere davvero utile.

Per ulteriori informazioni, consulta la documentazione ufficiale che è piuttosto ricca e ben dettagliata.


42

Per ottenere i dettagli dell'ultimo record

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

Per ottenere l'ultimo ID record

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

14

Le collezioni Laravel hanno il metodo ultimo

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

Questo è il modo migliore per farlo.


16
Volevo solo sottolineare che il all()metodo carica effettivamente tutti gli elementi. Questo non funzionerà su una tabella con milioni di record.
Steven Jeffries,

1
Oltre al commento di Steven Jeffries, vorrei sottolineare che la chiamata last()restituisce una singola istanza Eloquent e non una Collezione, e invocare pluck()equivale a chiamare Model::all()->pluck('name'), restituendo quindi l' nameattributo di tutte le righe nella tabella
ivcandela

5
Questo metodo in realtà è peggio. Stai recuperando l'ultimo raw usando l'esecuzione di PHP invece di farlo come livello DB. Che cosa succede se la tabella ha milioni di raw, allora sai quanto inefficiente può essere?
Bhaskar Dabhi,

Questo è il modo migliore per farlo. - No! Mai stato, mai lo sarà. Carichi tutte le righe anziché solo quella di cui hai bisogno.
René Roth,

11

Prova questo :

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

1
Ciò restituirà più righe. Ha bisogno di una sola fila. first () lo aiuterà con la clausola orderBy ().
Tahir Afridi,

Questo potrebbe non riuscire a ottenere l'ultima riga effettiva se due righe vengono inserite entro 1 secondo (effettivamente causato problemi nel test unitario).
chili

1
Su una tabella di grandi dimensioni ciò causerà un'eccezione di memoria insufficiente perché, come indicato da @TahirAfridi, questo caricherà tutte le righe in memoria.
Rihards,

6

Puoi utilizzare l'ultimo ambito fornito da Laravel con il campo che desideri filtrare, supponiamo che verrà ordinato per ID, quindi:

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

Quindi, in questo modo, puoi evitare di ordinare per created_atcampo di default su Laravel.


5

Per ottenere i dettagli dell'ultimo record, utilizzare il codice seguente:

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

Non usarlo. Questa è una brutta pratica, esiste un ambito latest () che fornisce accesso diretto all'ultima riga inserita.
Working Pig

3

Un altro modo fantasioso per farlo in Laravel 6.x (Incerto ma deve funzionare anche per 5.x):

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

Puoi anche accedere ai campi:

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


Funziona anche per me in Laravel 5.8, ho appena pubblicato la risposta prima di vedere la tua
Abbaglia il

1
Una piccola spiegazione su come Laravel fa questo dietro le quinte e perché questo è pericoloso per un set di dati di grandi dimensioni, il get()metodo prenderà tutto da your_tablee genererà una raccolta e il last()metodo otterrà l'ultimo elemento da quella raccolta. Quindi avrai già tutti i dati della tabella caricati in memoria (errato). Dovresti semplicemente usare `DB :: table ('items') -> latest () -> first ();` dietro la scena esegue `orderBy ($ column, 'desc')` e recupera il primo record.
Anuj Shrestha,


1

Se stai cercando la riga effettiva che hai appena inserito con Laravel 3 e 4 quando esegui un'azione saveo createsu un nuovo modello come:

$user->save();

-o-

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

quindi l'istanza del modello inserita verrà restituita e potrà essere utilizzata per ulteriori azioni come il reindirizzamento alla pagina del profilo dell'utente appena creato.

La ricerca dell'ultimo record inserito funziona su un sistema a basso volume funzionerà quasi sempre, ma se si devono inserire inserimenti contemporaneamente, si può finire per interrogare per trovare il record sbagliato. Questo può davvero diventare un problema in un sistema transazionale in cui è necessario aggiornare più tabelle.


1

In qualche modo tutto quanto sopra non sembra funzionare per me in laravel 5.3, quindi ho risolto il mio problema usando:

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

spero di riuscire a salvare qualcuno.


1

Usarlo Model::where('user_id', $user_id)->latest()->get()->first(); restituirà solo un record, se non lo trova, tornerà null. Spero che questo possa aiutare.


0

Se la tabella ha un campo data, questa ( User::orderBy('created_at', 'desc')->first();) è la soluzione migliore, credo. Ma non esiste un campo data, Model ::orderBy('id', 'desc')->first()->id;è la soluzione migliore, ne sono sicuro.


0

essere consapevoli del fatto che last(), latest()non sono deterministiche se siete alla ricerca di un sequenziale o di un evento / registrazione ordinato. Gli ultimi / recenti record possono avere lo stesso created_attimestamp esatto e ciò che si ottiene non è deterministico. Così orderBy(id|foo)->first(). Altre idee / suggerimenti su come essere deterministici sono i benvenuti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.