Sélectionnez la dernière ligne du tableau


163

Je souhaite récupérer le dernier fichier inséré dans ma table. Je sais que la méthode first()existe et vous fournit le premier fichier du tableau mais je ne sais pas comment obtenir le dernier insert.


Voir aussi stackoverflow.com/questions/33321447/… Comment trier une relation existante (hasMany)
Tarek Adam

Ceci est pour toute personne demandant et répondant à propos de Laravel. N'oubliez pas qu'il est important de spécifier de quelle version de Laravel vous parlez. En général, les versions 4 et 5 présentent des différences et les anciennes versions aussi.
Heroselohim

Réponses:


224

Vous devrez classer par le même champ que vous commandez maintenant, mais en ordre décroissant. Par exemple, si vous avez un horodatage lorsque le téléchargement a été appelé upload_time, vous feriez quelque chose comme ceci;

Pour Pre-Laravel 4

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

Pour Laravel 4 et plus

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

Pour Laravel 5.7 et versions ultérieures

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

Cela ordonnera les lignes de la table des fichiers par heure de téléchargement, ordre décroissant et prendra la première. Ce sera le dernier fichier téléchargé.


15
Pour Laravel 4, cela devrait être orderBy, pasorder_by
Jared Eitnier

9
Lorsque vous utilisez ORM, c'est une manière correcte:User::orderby('created_at', 'desc')->first();
Cas Bloem

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

9
Pourquoi utilisez-vous la colonne created_at? Beaucoup plus rapide à utiliser l'ID de clé primaire. Laravel 5.x Files::orderBy(id', 'desc')->first();Trier par date fonctionne plus longtemps car la date est une chaîne et probablement non indexée. Alors que la clé primaire est indexée et fonctionne très rapidement. Même si created_at est indexé, il s'agit d'une chaîne indexée et non de INT en cas de primaire. La chaîne d'index a moins de performances.
KorbenDallas

4
Le commentaire @KorbenDallas devrait être la réponse car parfois orderBy('created_at', 'desc')ne vous donne pas la dernière ligne. Exemple: 3 lignes peuvent avoir exactement la même valeur TIMESTAMP et avec orderBy('created_at', 'desc')vous obtiendrez la première des 3 (qui n'est pas nécessairement la dernière ligne)
viery365

111

Utilisez la dernière portée fournie par Laravel hors de la boîte.

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

De cette façon, vous ne récupérez pas tous les enregistrements. Un raccourci plus agréable pour orderBy.


7
Notez que cette méthode utilise la created_atcolonne auto-générée ($timestamps = true)dans le modèle, mais peut être désactivée à souhait pour que vous ayez une erreur si non définie
Plotisateur

J'utilise Laravel 5.7 et j'essaie de le faire sur un modèle récupère toujours tous les enregistrements pour moi.
CJ Dennis

1
Notez que si vous avez plusieurs enregistrements ajoutés dans la même seconde, l'heure created_at sera la même pour ces enregistrements et par conséquent, l'enregistrement renvoyé par latest () peut ne pas être l'enregistrement que vous attendez.
F3CP

Notez que vous n'avez pas besoin d'une colonne «created_at». Vous pouvez spécifier à partir de quelle colonne vous voulez la dernière. Par exemple: Model :: latest ('dateColumn') -> first ();
Tom

Cela peut ne pas obtenir la dernière ligne réelle si deux lignes sont insérées dans un délai de 1 seconde (cela a en fait causé des problèmes dans les tests unitaires).
chili

75

Vous n'avez jamais mentionné si vous utilisiez Eloquent, l'ORM par défaut de Laravel ou non. Dans le cas où vous l'êtes, disons que vous voulez obtenir la dernière entrée d'une table User, par created_at, vous pourriez probablement faire comme suit:

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

Tout d'abord, il classe les utilisateurs par champ created_at, par ordre décroissant, puis il prend le premier enregistrement du résultat.

Cela vous renverra une instance de l'objet User, pas une collection. Bien sûr, pour utiliser cette alternative, vous devez avoir un modèle User, étendant la classe Eloquent. Cela peut sembler un peu déroutant, mais il est vraiment facile de commencer et ORM peut être vraiment utile.

Pour plus d'informations, consultez la documentation officielle qui est assez riche et bien détaillée.


42

Pour obtenir les détails du dernier enregistrement

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

Pour obtenir l'identifiant du dernier enregistrement

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

14

Les collections Laravel ont la dernière méthode

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

C'est la meilleure façon de procéder.


16
Je voulais juste souligner que la all()méthode charge en fait tous les éléments. Cela ne fonctionnera pas sur une table avec des millions d'enregistrements.
Steven Jeffries

1
En plus du commentaire de Steven Jeffries, je voudrais souligner que l'appel last()renvoie une seule instance Eloquent et non une collection, et appeler pluck()cela équivaut à appeler Model::all()->pluck('name'), donc renvoyer l' nameattribut de toutes les lignes de la table
ivcandela

5
Cette méthode est pire en fait. Vous récupérez le dernier brut en utilisant l'exécution PHP au lieu de le faire au niveau de la base de données. Et si la table contient des millions de matières premières, alors vous savez à quel point elle peut être inefficace?
Bhaskar Dabhi

C'est la meilleure façon de procéder. - Non! Cela n'a jamais été, ne le sera jamais. Vous chargez toutes les lignes au lieu de celle dont vous avez besoin.
René Roth

11

Essaye ça :

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

1
Cela renverra plusieurs lignes. Il a besoin d'une seule rangée. first () l'aidera avec la clause orderBy ().
Tahir Afridi

Cela peut ne pas obtenir la dernière ligne réelle si deux lignes sont insérées dans un délai de 1 seconde (cela a en fait causé des problèmes dans les tests unitaires).
chili

1
Sur une grande table, cela provoquera une exception de mémoire insuffisante car, comme @TahirAfridi l'a mentionné, cela chargera toutes les lignes en mémoire.
Rihards

6

Vous pouvez utiliser la dernière portée fournie par Laravel avec le champ que vous souhaitez filtrer, disons qu'il sera trié par ID, puis:

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

Ainsi, vous pouvez éviter de commander par created_atchamp par défaut chez Laravel.


5

Pour obtenir les détails du dernier enregistrement, utilisez le code ci-dessous:

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

Ne l'utilisez pas. C'est une très mauvaise pratique car il existe une dernière portée (), elle fournit un accès direct à la dernière ligne insérée.
Working Pig

3

Une autre façon sophistiquée de le faire dans Laravel 6.x (Incertain mais doit également fonctionner pour 5.x):

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

Vous pouvez également accéder aux champs:

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


Fonctionne aussi pour moi dans Laravel 5.8, je viens de poster la réponse avant de voir la vôtre
Dazzle

1
Une petite explication sur la façon dont laravel fait cela dans les coulisses et pourquoi cela est dangereux pour un grand ensemble de données, la get()méthode récupérera tout your_tableet générera une collection et la last()méthode obtiendra le dernier élément de cette collection. Donc, vous aurez déjà toutes les données de la table chargées sur votre mémoire (mauvaise). Vous devez simplement utiliser `DB :: table ('items') -> latest () -> first ();` derrière la scène, il exécute `orderBy ($ column, 'desc')` et récupère le premier enregistrement.
Anuj Shrestha le


1

Si vous recherchez la ligne réelle que vous venez d'insérer avec Laravel 3 et 4 lorsque vous effectuez une action saveou createsur un nouveau modèle comme:

$user->save();

-ou-

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

puis l'instance de modèle insérée sera retournée et pourra être utilisée pour d'autres actions telles que la redirection vers la page de profil de l'utilisateur qui vient d'être créé.

La recherche du dernier enregistrement inséré fonctionne sur un système à faible volume fonctionnera presque tout le temps, mais si jamais vous devez insérer des insertions en même temps, vous pouvez finir par interroger pour trouver le mauvais enregistrement. Cela peut vraiment devenir un problème dans un système transactionnel où plusieurs tables doivent être mises à jour.


1

D'une manière ou d'une autre, tout ce qui précède ne semble pas fonctionner pour moi dans laravel 5.3, j'ai donc résolu mon propre problème en utilisant:

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

j'espère pouvoir renflouer quelqu'un.


1

Utilisez- Model::where('user_id', $user_id)->latest()->get()->first(); le ne retournera qu'un seul enregistrement, s'il n'est pas trouvé, il retournera null. J'espère que cela aidera.


0

Si la table a un champ de date, c'est ( User::orderBy('created_at', 'desc')->first();) la meilleure solution, je pense. Mais il n'y a pas de champ de date, Model ::orderBy('id', 'desc')->first()->id;c'est la meilleure solution, j'en suis sûr.


0

soyez conscient que last(), latest()ne sont pas déterministes si vous recherchez un enregistrement séquentiel ou événement / ordonné. Les derniers enregistrements / récents peuvent avoir exactement le même created_athorodatage, et que vous récupérez n'est pas déterministe. Alors fais orderBy(id|foo)->first(). D'autres idées / suggestions sur la façon d'être déterministe sont les bienvenues.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.