Selecione Última linha na tabela


163

Gostaria de recuperar o último arquivo inserido na minha tabela. Eu sei que o método first()existe e fornece o primeiro arquivo da tabela, mas não sei como obter a última inserção.


Ver também stackoverflow.com/questions/33321447/... Como classificar um um relacionamento existente (hasMany)
Tarek Adam

Isto é para qualquer pessoa que pergunte e responda sobre o Laravel. Lembre-se de que é importante especificar qual versão do Laravel você está falando. Geralmente as versões 4 e 5 têm diferenças e versões mais antigas também.
Heroselohim 25/05

Respostas:


224

Você precisará solicitar pelo mesmo campo que está solicitando agora, mas descendente. Como exemplo, se você tiver um carimbo de data / hora quando o upload for chamado upload_time, faça algo assim;

Para o Pré-Laravel 4

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

Para o Laravel 4 em diante

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

Para o Laravel 5.7 e seguintes

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

Isso ordenará as linhas na tabela de arquivos por tempo de upload, ordem decrescente e a primeira. Este será o último arquivo carregado.


15
Para o Laravel 4, isso deveria ser orderBy, nãoorder_by
Jared Eitnier 17/10

9
Quando você usa ORM, esta é a maneira correta:User::orderby('created_at', 'desc')->first();
Cas Bloem

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

9
Por que você está usando a coluna created_at? Muito mais rápido para usar o ID da chave primária. A Files::orderBy(id', 'desc')->first();ordem por data do Laravel 5.x funciona mais porque a data é string e provavelmente não indexada. Enquanto a chave primária é indexada e funciona super rápido. Mesmo se created_at indexado, é uma string indexada e não INT no caso de primário. A sequência de índice tem menos desempenho.
precisa saber é o seguinte

4
O comentário do @KorbenDallas deve ser a resposta, porque às vezes orderBy('created_at', 'desc')não fornece a última linha. Exemplo: 3 linhas pode ter exatamente o mesmo valor TIMESTAMP e com orderBy('created_at', 'desc')que você vai ter o primeiro dos 3 (que não é necessariamente a última linha)
viery365

111

Use o escopo mais recente fornecido pelo Laravel imediatamente.

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

Dessa forma, você não está recuperando todos os registros. Um atalho melhor para orderBy.


7
Observe que esse método usa a created_atcoluna gerada automaticamente ($timestamps = true)no modelo, mas pode ser desabilitada quando desejar, para que você tenha um erro se indefinido
Plotisateur

Estou usando o Laravel 5.7 e tentando fazer isso em um modelo ainda recupera todos os registros para mim.
CJ Dennis

1
Observe que se você tiver vários registros adicionados no mesmo segundo, o horário created_at será o mesmo para esses registros e, portanto, o registro retornado por latest () poderá não ser o registro que você espera que seja.
F3CP 23/01/19

Observe que você não precisa de uma coluna 'created_at'. Você pode especificar de qual coluna deseja a mais recente. Por exemplo: Model :: latest ('dateColumn') -> first ();
Tom

Isso pode falhar na obtenção da última linha real se duas linhas forem inseridas em 1 segundo (realmente causaram problemas no teste de unidade).
Chili

75

Você nunca mencionou se está usando o Eloquent, o ORM padrão do Laravel ou não. Caso seja, digamos que você queira obter a entrada mais recente de uma tabela de usuário, por created_at, você provavelmente poderá fazer o seguinte:

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

Primeiro, ele ordena os usuários pelo campo created_at, descendente, e depois pega o primeiro registro do resultado.

Isso retornará uma instância do objeto Usuário, não uma coleção. Obviamente, para fazer uso dessa alternativa, você precisa ter um modelo de usuário, estendendo a classe Eloquent. Isso pode parecer um pouco confuso, mas é realmente fácil começar e o ORM pode ser realmente útil.

Para mais informações, consulte a documentação oficial, que é bastante rica e bem detalhada.


42

Para obter os detalhes do último registro

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

Para obter o último ID do registro

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

14

As coleções do Laravel têm o método last

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

Essa é a melhor maneira de fazer isso.


16
Só queria ressaltar que o all()método realmente carrega todos os itens. Isso não funcionará em uma tabela com milhões de registros.
Steven Jeffries

1
Além do comentário de Steven Jeffries, gostaria de salientar que a chamada last()retorna uma única instância Eloquent e não uma Collection, e a chamada pluck()igual a chamada Model::all()->pluck('name'), retornando, portanto, o nameatributo de todas as linhas da tabela
ivcandela

5
Este método é pior, na verdade. Você está buscando a última raw usando a execução do PHP em vez de fazê-lo no nível do banco de dados. E se a tabela tiver milhões de dados brutos, você sabe o quão ineficiente pode ser?
Bhaskar Dabhi 23/11

Essa é a melhor maneira de fazer isso. - Não! Nunca foi, nunca será. Você carregaria todas as linhas em vez da que você precisa.
René Roth

11

Tente o seguinte:

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

1
Isso retornará várias linhas. Ele precisa de uma única linha. first () o ajudará com a cláusula orderBy ().
Tahir Afridi

Isso pode falhar na obtenção da última linha real se duas linhas forem inseridas em 1 segundo (realmente causaram problemas no teste de unidade).
Chili

1
Em uma tabela grande, isso causará uma exceção de falta de memória porque, como @TahirAfridi mencionou, isso carregará todas as linhas na memória.
Rihards

6

Você pode usar o escopo mais recente fornecido pelo Laravel com o campo que deseja filtrar, digamos que ele será ordenado por ID e, em seguida:

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

Dessa forma, você pode evitar pedidos por created_atcampo por padrão no Laravel.


5

Para obter os detalhes do último registro, use o código abaixo:

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

Não use. Essa é uma prática muito ruim; há um escopo mais recente () que fornece acesso direto à última linha inserida.
Working Pig

3

Outra maneira sofisticada de fazer isso no Laravel 6.x (incerto, mas deve funcionar também para o 5.x):

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

Você também pode acessar os campos:

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


Também funciona para mim em Laravel 5.8, só postou a resposta antes de ver o seu
Dazzle

1
Uma pequena explicação sobre como o laravel faz isso nos bastidores e por que isso é perigoso para grandes conjuntos de dados, o get()método buscará tudo your_tablee gerará uma coleção e o last()método obterá o último item dessa coleção. Portanto, você já terá todos os dados da tabela carregados na memória (incorretos). Você deve apenas usar `DB :: table ('items') -> latest () -> first ();` nos bastidores, ele executa `orderBy ($ column, 'desc')` e busca o primeiro registro.
Anuj Shrestha 17/04


1

Se você está procurando a linha real que você acabou de inserir com o Laravel 3 e 4 ao executar uma ação saveou createem um novo modelo como:

$user->save();

-ou-

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

a instância do modelo inserida será retornada e poderá ser usada para ações adicionais, como redirecionar para a página de perfil do usuário recém-criado.

Procurar o último registro inserido funciona no sistema de baixo volume funcionará quase o tempo todo, mas se você precisar inserir as inserções ao mesmo tempo, poderá acabar consultando para encontrar o registro errado. Isso pode realmente se tornar um problema em um sistema transacional em que várias tabelas precisam ser atualizadas.


1

De alguma forma, todas as opções acima parecem não funcionar para mim no laravel 5.3, então resolvi meu próprio problema usando:

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

espero que seja capaz de salvar alguém.


1

Use Model::where('user_id', $user_id)->latest()->get()->first(); -o para retornar apenas um registro; caso contrário, ele retornará null. Espero que isso ajude.


0

Se a tabela tiver um campo de data, essa ( User::orderBy('created_at', 'desc')->first();) é a melhor solução, eu acho. Mas não há campo de data, Model ::orderBy('id', 'desc')->first()->id;é a melhor solução, tenho certeza.


0

estar ciente de que last(), latest()não são deterministas se você estiver procurando por um seqüencial ou evento / record ordenada. Os últimos / recentes registros podem ter exatamente o mesmo created_atregistro de data e hora, e o retorno é não determinístico. O mesmo acontece orderBy(id|foo)->first(). Outras idéias / sugestões sobre como ser determinístico são bem-vindas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.