paulo-leo / laravel-qjs
Descrição do seu pacote
This package is auto-updated.
Last update: 2024-04-25 19:40:14 UTC
README
O Laravel QJS é um pacote PHP desenvolvido especificamente para aplicações Laravel, mas também é compatível com o Lumen. Ele oferece uma maneira eficiente e intuitiva de gerar relatórios usando uma linguagem baseada na estrutura JSON.
Introdução ao QJS: Uma Linguagem Declarativa para Geração Dinâmica de Relatórios
O QJS é uma linguagem declarativa que pode ser escrita tanto em JSON quanto em arrays associativos do PHP. Desenvolvida por Paulo Leonardo Da S. Cassimiro, sua principal finalidade é resolver o desafio recorrente de geração de relatórios. A criação de relatórios é uma tarefa altamente dinâmica, cuja complexidade varia de acordo com o cenário específico. A proposta por trás dessa linguagem é permitir o armazenamento de instruções para a renderização de relatórios em arquivos de texto ou campos de banco de dados, podendo ser chamados em tempo real.
A ideia de construir o QJS usando o formato JSON foi inspirada no uso de estados de componentes em aplicações reativas, como React, Vue, Angular, entre outras. Isso possibilita a construção de relatórios em tempo real, dependendo da implementação. As instruções da linguagem seguem as mesmas regras do SQL comum, com a diferença de que as declarações não precisam seguir uma ordem específica, sendo o único campo obrigatório o from, enquanto os demais refinam o seu relatório.
Em resumo, o QJS pode ser considerado um protocolo para a criação de relatórios baseados em estados JSON.
Uma consulta QJS pode ser interpretada da seguinte maneira:
{ "from":"categories", "where":"created_at,between,$nowsub:30;$now" }
Nesta consulta, especificamos que um relatório será gerado para todas as categorias (from) do sistema, onde (where) as categorias foram criadas (created_at) dentro do intervalo (between) dos últimos 30 dias até a data atual ($nowsub:30;$now). Os placeholders $nowsub e $now são métodos avançados de data que podem ser utilizados em qualquer filtro, exceto nos operadores in e !in. O prefixo $ indica o uso de um comando interno.
Recursos
-
Sintaxe Simples: A estrutura de uma consulta QJS é simples e não requer uma ordem específica para os comandos.
-
Flexibilidade: O comando "from" é o único obrigatório para gerar um relatório básico, mas é possível realizar relacionamentos entre entidades do esquema do banco de dados, executar agregações e subconsultas nas linhas e utilizar comandos avançados de datas nos filtros dos relatórios.
-
Facilidade de Uso: A estrutura do QJS pode ser facilmente salva em uma string e executada diretamente a partir de uma tabela de relatórios.
-
Simplificação de Relatórios Complexos: Uma das maiores motivações para o desenvolvimento deste recurso é a simplificação de relatórios complexos, tornando o processo mais ágil e eficiente.
-
Conversão Nativa: O QJS oferece suporte nativo para a conversão dos relatórios gerados em tabelas HTML e XLS.
Instalação via composer:
composer require paulo-leo/laravel-qjs:dev-main
Exemplo de uso
<?php namespace App\Http\Controllers; use PauloLeo\LaravelQJS\QJS; class ReportController extends Controller{ public function render(Request $request){ $qjs = new QJS; $query = $request->all(); $report = $qjs->render($query); if($report->render){ response()->json($report->data,200); }else{ response()->json($report,422); } } }
Convertendo em XLS(Excel) ou HTML
<?php namespace App\Http\Controllers; use PauloLeo\LaravelQJS\QJS; public function render(Request $request){ $qjs = new QJS; $query = $request->all(); $report = $qjs->render($query); if($request->type == 'xls' && $report->render) return $qjs->toXLS($report->data); if($request->type == 'html' && $report->render) return $qjs->toHTML($report->data); return response()->json($report); } }
O método render é o núcleo da classe, responsável por processar a consulta que pode ser especificada em formato JSON ou como um array associativo. Seu primeiro parâmetro é a própria consulta, enquanto o segundo refere-se aos filtros aplicados. Esses filtros podem ser passados como um array associativo ou como uma string em formato JSON.
O método render sempre retorna um objeto contendo a chave render, a qual pode assumir os valores true ou false. Quando true, indica que a renderização do relatório foi bem-sucedida, devolvendo, então, a chave data contendo os dados do relatório. Esses dados são organizados como um array indexado, onde cada índice contém um objeto com as informações a serem apresentadas no relatório.
Aqui está um exemplo de uso:
$query = array( "from" => "users" ); $filter = array( array("name", "!=", "Carlos") ); $qjs = new QJS; return response()->json($qjs->render($query, $filter));
Guia QJS
Listar todos os usuários do sistema:
{ "from": "users" }
Listar todos os usuários e trazer somente os campos id e name:
{ "from": "users", "rows": "id, name" }
Listar todos os usuários e trazer somente os campos id e name e renomeia o campo name para cliente:
{ "from": "users", "rows": "id, name as cliente" }
Listar todos os usuários, trazendo apenas os campos id e name, e contar quantos existem:
{ "from": "users", "rows": "id, name, $count(*) as total", "group":"id,name" }
Observação: Sempre que executar uma subconsulta, adicione o caractere $ antes do comando SQL ou da função de agregação desejada. O $ indica que você está realizando uma subconsulta ou uma função de agregação. Além disso, ao utilizar uma subconsulta com campos não agregados, é importante incluir o comando group e passar os campos não agregados nele para garantir que o resultado seja agrupado corretamente. No entanto, no exemplo abaixo, não é necessário usar o comando group, pois as regras do SQL se aplicam aqui:
{ "from": "users", "rows": "$count(*) as total" }
Você pode usar a declaração where para aplicar filtros ao seu relatórios:
{ "from": "users", "rows": "id, name", "where":"id,10" }
O comando acima busca o usuário ao qual o id é igual a "10", quando é omitido o operador, query considera como igual "=". Se você quiser passar um operador, você deverá escrever da seguinte maneira:
{ "from": "users", "rows": "id, name", "where":"id,!=,10" }
Para passar mais de um filtro, você pode escrever da seguinte forma:
{ "from": "users", "rows": "id, name", "where":[ ["id",">","1"], ["name","like","a%"] ] }
Para passar mais de um filtro, você pode escrever da seguinte forma:
{ "from": "users", "rows": "id, name", "where":[ ["id", ">", "1"], ["name", "like", "a%"] ] }
O mesmo código pode ser escrito assim:
{ "from": "users", "rows": "id, name", "where":["id,>,1","name,like,a%"] }
Se desejar passar um operador OR após o primeiro filtro, basta adicionar um quarto valor no filtro, um booleano true indicando que será aplicado o operador OR:
{ "from": "users", "rows": "id, name", "where":[ ["id",">","1"], ["name","like","a%",true]] }
Além disso, você pode usar os seguintes operadores para lidar com intervalos, valores nulos e listagem: Para intervalos entre dois valores, utilize o operador between:
{ "from": "users", "rows": "id, name", "where":[ ["id","between","1|10"] ] }
Para valores nulos:
{ "from": "users", "rows": "id, name", "where":[ ["id","null"] ] }
Para uma lista de valores:
{ "from": "users", "rows": "id, name", "where":[ ["id","in",[1,2,3]] ] }
Se desejar negar a busca utilizando esses operadores, basta adicionar o caractere ! na frente do operador between, null e in:
{ "from": "users", "rows": "id, name", "where":[ ["id","!null"], ["id","!in",[1,2,3]], ["id","!between","1|10"] ] }
Agora, se você declarou um método de agregação na row e deseja filtrar a agregação, pode usar a declaração having da seguinte forma:
{ "from": "users", "rows": "id, name, $count(*) as total", "group": "id, name", "having": [ ["total", ">", "10"] ] }
Você também pode ordenar o seu relatório utilizando a declaração order. Aqui estão dois exemplos de como fazer isso: Ordenar por uma coluna em ordem descendente:
{ "from": "users", "order": "id,desc" }
Ordenar por múltiplas colunas, onde a primeira é ordenada em ordem descendente e a segunda em ordem ascendente:
{ "from": "users", "order": ["id,desc","name"] }
A funcionalidade de junção de entidades no QJS assemelha-se aos JOINS do SQL, utilizando três métodos fundamentais. Com base na teoria dos conjuntos, é possível empregar os métodos "join" para uma junção total, quando há referência entre as duas entidades; "left", quando a prioridade é dada à tabela à esquerda; e "right", quando a prioridade é atribuída à tabela à direita.
{ "from": "users", "rows":"users.id,users.name,categories.name as category", "join":"categories,categories.id,users.category_id" }
Para realizar múltiplas junções, segue-se a seguinte sintaxe:
{ "from": "users", "rows": "users.id, users.name, categories.name as category", "left": [ "categories, categories.id, users.category_id", "drivers, drivers.id, users.driver_id" ] }
Alternativamente, pode-se utilizar a seguinte estrutura:
{ "from": "users", "rows": "users.id, users.name, categories.name as category", "left": [ ["categories", "categories.id", "users.category_id"], ["drivers", "drivers.id", "users.driver_id"] ] }