Como consultar entre duas datas usando Laravel e Eloquent?

122

Estou tentando criar uma página de relatório que mostra relatórios de uma data específica para uma data específica. Este é meu código atual:

$now = date('Y-m-d');
$reservations = Reservation::where('reservation_from', $now)->get();

O que isso faz em SQL simples é select * from table where reservation_from = $now.

Tenho esta consulta aqui, mas não sei como convertê-la em consulta eloquente.

SELECT * FROM table WHERE reservation_from BETWEEN '$from' AND '$to

Como posso converter o código acima em uma consulta eloquente? Agradeço antecipadamente.

wobsoriano
fonte
qual é o formato da data reservation_from. você pode usar os valores de carbono com base nisso.
Athi Krishnan
o formato da data é TIMESTAMP @AthiKrishnan
wobsoriano
4
seria como Reservation::where('reservation_from', '>=', Carbon::createFromDate(1975, 5, 21);) ->where('reservation_from', '<=', Carbon::createFromDate(2015, 5, 21);)->get(),;
Athi Krishnan

Respostas:

247

O whereBetweenmétodo verifica se o valor de uma coluna está entre dois valores.

$from = date('2018-01-01');
$to = date('2018-05-02');

Reservation::whereBetween('reservation_from', [$from, $to])->get();

Em alguns casos, você precisa adicionar o intervalo de datas dinamicamente. Com base no comentário de @Anovative , você pode fazer o seguinte:

Reservation::all()->filter(function($item) {
  if (Carbon::now->between($item->from, $item->to) {
    return $item;
  }
});

Se quiser adicionar mais condição, você pode usar orWhereBetween. Se quiser excluir um intervalo de datas, você pode usar whereNotBetween.

Reservation::whereBetween('reservation_from', [$from1, $to1])
  ->orWhereBetween('reservation_to', [$from2, $to2])
  ->whereNotBetween('reservation_to', [$from3, $to3])
  ->get();

Outras cláusulas úteis em que: whereIn, whereNotIn, whereNull, whereNotNull, whereDate, whereMonth, whereDay, whereYear, whereTime, whereColumn, whereExists, whereRaw.

Laravel docs sobre Where Clauses.

Peter Kota
fonte
Como isso seria tratado se $frome $tofossem datas dinâmicas pertencentes ao modelo? Como em há um effective_ate expires_atcampos e eu quero consultar para ver se o item atual está dentro desse intervalo. Tentei each()com um if that use Carbon::now()->between( ... ), porém ainda retorna todos os resultados.
Rockin4Life33
4
EDIT para meu comentário acima: Negligenciado filter(), isso resolveu o problema. MyModel::all()->where('column', 'value')->filter(function ($item) { if (Carbon::now->between($item->effective_at, $item->expires_at)) { return $item; } })->first();
Rockin4Life33
1
Obrigado @Anovative pelo seu comentário útil. Vou atualizar minha resposta com base em seu comentário.
Peter Kota
só vai dar a partir do registro da data.
Muhammad
1
Existe um problema com o segundo método. Ele carregará todos os registros do banco de dados para a memória e somente então fará a filtragem.
Jino Antony
12

Outra opção se o seu campo for em datetimevez de date( embora funcione para os dois casos ):

$fromDate = "2016-10-01";
$toDate   = "2016-10-31";

$reservations = Reservation::whereRaw(
  "(reservation_from >= ? AND reservation_from <= ?)", 
  [$fromDate." 00:00:00", $toDate." 23:59:59"]
)->get();
tomloprod
fonte
1
tecnicamente não precisaria ser $ toDate. "23: 59.59.999"?
stevepowell2000
@ stevepowell2000 Depende do seu banco de dados, no meu caso armazenamos a data com este formato 'AAAA-MM-DD HH: MM: SS' em um campo datetime mysql, sem precisão de microssegundos. Informações relacionadas: dev.mysql.com/doc/refman/8.0/en/datetime.html
tomloprod
Ótimo ponto. Então, se ele era um campo de data e hora ou timestamp que podem ir todo o caminho até a 23: 59: 59,999999 "O valor de um DATETIME ou TIMESTAMP pode incluir uma fuga fracionários segundos parte em até microssegundos (6 dígitos) de precisão."
stevepowell2000
1
obrigado você tem me ajudado a fazer minha tarefa antes! amo essa resposta mano! :) -habie
Habie Smart
10

O seguinte deve funcionar:

$now = date('Y-m-d');
$reservations = Reservation::where('reservation_from', '>=', $now)
                           ->where('reservation_from', '<=', $to)
                           ->get();
Pᴇʜ
fonte
8

Se você deseja verificar se a data atual existe entre duas datas no banco de dados: => aqui a consulta obterá a lista de aplicativos se o aplicativo de e até a data de hoje existe na data de hoje.

$list=  (new LeaveApplication())
            ->whereDate('from','<=', $today)
            ->whereDate('to','>=', $today)
            ->get();
John
fonte
7

Experimente isto:

Como você busca com base em um único valor de coluna, pode simplificar sua consulta da mesma forma:

$reservations = Reservation::whereBetween('reservation_from', array($from, $to))->get();

Recuperar com base na condição: laravel docs

Espero que tenha ajudado.

ArtisanBay
fonte
6

E eu criei o escopo do modelo

Mais sobre escopos:

Código:

   /**
     * Scope a query to only include the last n days records
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeWhereDateBetween($query,$fieldName,$fromDate,$todate)
    {
        return $query->whereDate($fieldName,'>=',$fromDate)->whereDate($fieldName,'<=',$todate);
    }

E no controlador, adicione a Biblioteca de Carbono ao topo

use Carbon\Carbon;

OU

use Illuminate\Support\Carbon;

Para obter o registro dos últimos 10 dias a partir de agora

 $lastTenDaysRecord = ModelName::whereDateBetween('created_at',(new Carbon)->subDays(10)->toDateString(),(new Carbon)->now()->toDateString() )->get();

Para obter os últimos 30 dias registro dos partir de agora

 $lastTenDaysRecord = ModelName::whereDateBetween('created_at',(new Carbon)->subDays(30)->toDateString(),(new Carbon)->now()->toDateString() )->get();
Manojkiran.A
fonte
1
O segundo parâmetro WhereDateBetween precisa ser uma matriz.
Mkey
É apenas um escopo do modelo, não é o método Builder
Manojkiran.A
Oh sim, perdi isso de alguma forma. Meu mal :)
Mkey
5

Se você precisar saber quando um campo de data e hora deve ser assim.

return $this->getModel()->whereBetween('created_at', [$dateStart." 00:00:00",$dateEnd." 23:59:59"])->get();
MIGUEL LOPEZ ARIZA
fonte
2
Olá, bem-vindo ao Stack Overflow. Ao responder uma pergunta que já tem muitas respostas, certifique-se de adicionar alguns insights adicionais sobre por que a resposta que você está fornecendo é substantiva e não apenas ecoando o que já foi examinado pelo autor original. Isso é especialmente importante em respostas "somente código", como a que você forneceu.
chb
3

Eu sei que isso pode ser uma questão antiga, mas acabei de me ver em uma situação em que tive que implementar esse recurso em um aplicativo Laravel 5.7. Abaixo está o que funcionou comigo.

 $articles = Articles::where("created_at",">", Carbon::now()->subMonths(3))->get();

Você também precisará usar Carbon

use Carbon\Carbon;
Excelente Lawrence
fonte