Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Consulta com Filtro via Eloquent ORM

Uma coisa muito comum em um sistema é a filtragem de registros em uma consulta. Apesar de comum, acho muito exaustivo desenvolver uma filtragem usando SQL's e seus WHERE's e INNER JOIN's. Como isso seria feito usando os Modelos Eloquent? Na verdade li a documentação, mas não encontrei o que eu queria (ou não percebi).

Um exemplo simples:

  • Dois modelos relacionados (ou seja, duas tabelas no banco): Produtos e Categorias.

  • Uma view com formulário de 3 inputs: produto, preço e categoria.

  • Ao preencher os campos e submeter o formulário, os parâmetros serão usados para criar a query no Controller.

  • Mostrar o resultado filtrado numa view em uma tabela.

Pelo o que eu pesquisei na documentação do Laravel, poderia fazer algo do tipo:

$produtos = Produto::all()
            ->where('produto', Request::input('produto'))
            ->where('preco', Request::input('preco'));

return view('lista')->with('produtos ' , $produtos );

Até aqui tudo bem, posso filtrar os produtos por nome e preço, mas ai vêm os questionamentos:

1 - Como filtrar os produtos por CATEGORIA através do campo categoria do meu formulário?

2 - Se um dos campos estiver VAZIO (ou todos), como NÃO filtrar por esse campo (ou seja, retornar TODOS)?

2 respostas

A resposta do 1 pode ser algo assim:

$produtos = Produto::whereHas('categoria', function ($query) {
    $query->where('id', Request::input('categoria_id'));
})->get();

A resposta 2 pode ser uma refatoração desse método pois ele precisa fazer menos coisas: extrair um método privado para filtrar esse Request e outro método para receber o RequestFiltrado.

solução!

Olá Ricardo, Depois de horas e horas estudando a documentação, juntando o que aprendi com o que você me mostrou, cheguei ao resultado que eu queria.

Porém, muito infelizmente, o código não alcançou o nível de simplicidade e clareza que eu esperava, pois ficou tão complexo quanto utilizar o SQL. Espero que essa não seja a melhor solução e que alguém consiga demonstrar uma forma mais viável e simples explorando toda a versatilidade do Laravel.

Bom, pra minha 1ª pergunta usei a sua solução. Pra 2ª pergunta usei o método when(teste,function()) que executa uma função quando teste do primeiro parâmetro for true. Então a lógica foi utilizar o campo enviado do formulário como teste e executar o where dentro da função, depois foi só juntar tudo. E o resultado foi esse:

$produtos = Produto::when(Request::input('produto'),function($query){
                            $query->where('nome_produto',Request::input('produto'));
                        })
                        ->when(Request::input('preco'),function($query){
                            $query->where('preco_produto',Request::input('preco'));
                        })
                        ->when(Request::input('categoria'), function($query){
                            $query->whereHas('categoria', function ($query) {
                                $query->where('nome_categoria',Request::input('categoria'));
                            });
                        })->get();