Há pouco tempo, fiz um tutorial ensinando como criar filtros de pesquisa no Laravel. Porém outra dificuldade que vejo entre os desenvolvedores que utilizam este framework é quando se trata de filtrar as pesquisas através de intervalo de datas.
Nesse tutorial vamos ver que pesquisar por datas no Laravel é algo simples.
Pesquisando datas por intervalo no Laravel
Tomando como exemplo uma pesquisa de Produtos, vamos utilizar dois inputs para identificar um período inicial e um período final para pesquisar os dados no banco. Neste tutorial, utilizaremos como base o campo created_at
.
Código Blade:
<input type="text" value="{{ request('data_inicio') }} name="data_inicio" />
<input type="text" value="{{ request('data_fim') }} name="data_fim" />
@foreach($produtos as $produto)
<div>{{ $produto->nome }}</div>
@endforeach
Código Controller:
class ProdutosController extends Controller
{
public function index(Request $request)
{
$produtos = Produto::paginate();
return view('produtos.index', compact('produtos'));
}
}
Validando o formato das datas
Geralmente, aqui no Brasil, usamos o formato DD/MM/AAAA
para as datas. Nesse caso, precisamos de converter esses valores para DateTime
ou Carbon
, que tornará mais fácil nosso trabalho no Laravel. Podemos utilizar o método DateTime::createFromFormat
, por exemplo:
$data_inicio = \DateTime::createFromFormat('d/m/Y', $request->get('data_inicio'));
$data_fim = \DateTime::createFromFormat('d/m/Y', $request->get('data_fim'));
if ($data_inicio && $data_fim) {
// Consulta aqui
}
Acima verificamos se $data_inicio
e $data_fim
são false
, pois DateTime::createFromFormat
retornará false
caso a data seja inválida. Já o Carbon
, costuma retornar uma exceção caso seja inválido.
É possível utilizar o Validator
, se desejar retornar um erro, caso uma data inválida seja passada pelo cliente. Talvez seja o melhor caminho para manter a integridade dos valores utilizados ao realizar a pesquisa.
Código com Validator
:
public function index(Request $request)
{
$request->validate([
'data_inicio' => 'nullable|date_format:d/m/Y',
'data_fim' => 'required_if:data_inicio|date_format:d/m/Y',
]);
$data_inicio = \DateTime::createFromFormat('d/m/Y', $request->get('data_inicio'));
$data_fim = \DateTime::createFromFormat('d/m/Y', $request->get('data_fim'));
if ($data_inicio && $data_fim) {
// Consulta aqui
}
}
Filtrando os dados da pesquisa por datas
Agora, que temos as datas convertidas, podemos usar os valores para realizar a pesquisa nos registros do banco de acordo com as datas. Vamos então usar a função whereDate
do Laravel para fazer isso.
public function index(Request $request)
{
$query = Produto::query();
$request->validate([
'data_inicio' => 'nullable|date_format:d/m/Y',
'data_fim' => 'required_if:data_inicio|date_format:d/m/Y',
]);
$data_inicio = \DateTime::createFromFormat('d/m/Y', $request->get('data_inicio'));
$data_fim = \DateTime::createFromFormat('d/m/Y', $request->get('data_fim'));
if ($data_inicio && $data_fim) {
$query->whereDate('created_at', '>=', $data_inicio);
$query->whereDate('created_at', '<=', $data_fim);
}
$produtos = $query->paginate();
return view('produtos.index', compact('produtos'));
}
Note que no caso acima, diferente do costume dos vários tutoriais, não utilizei o whereBetween
. Isso porque geralmente, quando se usa o whereBetween
, é necessário adicionar à data de início o valor 00:00:00
e no fim, 23:59:59
, para não ter problemas com alguma hora registrada que acaba deixando de ser capturada. Para não termos que adicionar mais essa complexidade ao código, usei o whereDate
, pois internamente ele adiciona DATE(created_at)
na cláusula WHERE
da SQL.
A query gerada será algo parecido com isso:
SELECT * FROM produtos WHERE DATE(created_at) >= ? AND DATE(created_at) <= ?
Dessa forma, você consegue pesquisar por um intervalo de dados facilmente no Laravel.