paulo-leo/laravel-qjs

dev-main 2024-04-25 19:39 UTC

This package is auto-updated.

Last update: 2024-09-25 20:30:04 UTC


README

laravel-qjs 是一个专为 Laravel 应用程序开发的 PHP 包,但也兼容 Lumen。它提供了一个高效直观的方法来使用基于 JSON 结构的脚本语言生成报告。

QJS 简介:用于动态生成报告的声明式语言

QJS 是一种可以以 JSON 或 PHP 关联数组形式编写的声明式语言。由 Paulo Leonardo Da S. Cassimiro 开发,其主要目的是解决生成报告的常见挑战。生成报告是一项高度动态的任务,其复杂性随具体场景而变化。该语言的背后理念是允许将报告渲染指令存储在文本文件或数据库字段中,并可在实时调用。

使用 JSON 格式构建 QJS 的想法受到了 React、Vue、Angular 等响应式应用组件状态使用的启发。这使得根据实现情况在实时构建报告成为可能。该语言的指令遵循常见的 SQL 规则,区别在于声明不必遵循特定顺序,唯一必需的字段是 from,其余字段则进一步细化报告。

简而言之,QJS 可以被视为一个基于 JSON 状态创建报告的协议。

QJS 查询可以这样解释

      {
	"from":"categories",
	"where":"created_at,between,$nowsub:30;$now"
      }

在这个查询中,我们指定将生成系统所有类别(from)的报告,其中(where)类别是在过去 30 天内(between)创建的,直到当前日期($nowsub:30;$now)。$nowsub 和 $now 是可以在任何过滤器中使用的先进日期方法,但不能用于 in 和 !in 操作符。前缀 $ 表示使用内部命令。

资源

  • 简单语法: QJS 查询的结构简单,不需要特定的命令顺序。

  • 灵活性: “from” 命令是生成基本报告的唯一必需命令,但可以执行数据库模式实体之间的关系、在行上执行聚合和子查询,以及在报告过滤器中使用高级日期命令。

  • 易用性: QJS 的结构可以轻松保存为字符串,并直接从报告表执行。

  • 简化复杂报告: 开发此功能的主要动机之一是简化复杂报告,使过程更加敏捷和高效。

  • 原生转换: QJS 支持将生成的报告转换为 HTML 和 XLS 表格。

通过 composer 安装

    composer require paulo-leo/laravel-qjs:dev-main

使用示例

<?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);
               }      
         }  
  }
    

转换为 XLS(Excel)或 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);    
       }  
   }
    

render 方法是类的基础,负责处理可以指定为 JSON 格式或关联数组的查询。第一个参数是查询本身,第二个参数是应用的过滤器。这些过滤器可以以关联数组或 JSON 格式的字符串传递。

方法 render 总是返回一个包含键 render 的对象,该键可以取 true 或 false 的值。当为 true 时,表示报告渲染成功,然后返回包含报告数据的键 data。这些数据按索引数组组织,其中每个索引包含一个包含要在报告中展示的信息的对象。

以下是一个使用示例

$query = array(
    "from" => "users"
);

$filter = array(
    array("name", "!=", "Carlos")
);

$qjs = new QJS;

return response()->json($qjs->render($query, $filter));

QJS 指南

列出系统中的所有用户

{
  "from": "users"
}

列出所有用户,仅获取 id 和 name 字段

{
  "from": "users",
  "rows": "id, name"
}

列出所有用户,仅获取 id 和 name 字段,并将 name 字段重命名为 cliente

{
  "from": "users",
  "rows": "id, name as cliente"
}

列出所有用户,仅获取 id 和 name 字段,并计算存在多少个

{
  "from": "users",
  "rows": "id, name, $count(*) as total",
  "group":"id,name"
}

注意:每次执行子查询时,请在所需的 SQL 命令或聚合函数前添加字符 $。$ 表示您正在进行子查询或聚合函数。此外,当使用不包含聚合的字段进行子查询时,重要的是包含 group 命令并将不包含聚合的字段传递给它,以确保结果正确分组。然而,在下面的示例中,不需要使用 group 命令,因为这里的 SQL 规则适用

{
  "from": "users",
  "rows": "$count(*) as total"
}

您可以使用 where 子句来对报告应用过滤器

{
  "from": "users",
  "rows": "id, name",
  "where":"id,10"
}

上面的命令查找 id 等于 "10" 的用户,当省略操作符时,查询默认认为等于 "="。如果您想传递一个操作符,您应该这样写

{
  "from": "users",
  "rows": "id, name",
  "where":"id,!=,10"
}

要传递多个过滤器,您可以这样写

{
  "from": "users",
  "rows": "id, name",
  "where":[
  ["id",">","1"],
  ["name","like","a%"]
  ]
}

要传递多个过滤器,您可以这样写

{
  "from": "users",
  "rows": "id, name",
  "where":[
    ["id", ">", "1"],
    ["name", "like", "a%"]
  ]
}

同样的代码可以这样写

{
  "from": "users",
  "rows": "id, name",
  "where":["id,>,1","name,like,a%"]
}

如果您想在第一个过滤器之后传递 OR 操作符,只需在过滤器中添加一个第四个值,一个布尔值 true,表示将应用 OR 操作符

{
  "from": "users",
  "rows": "id, name",
  "where":[
  ["id",">","1"],
  ["name","like","a%",true]]
}

此外,您可以使用以下操作符来处理区间、空值和列表:对于两个值之间的区间,使用 between 操作符

{
  "from": "users",
  "rows": "id, name",
  "where":[
    ["id","between","1|10"]
  ]
}

对于空值

{
  "from": "users",
  "rows": "id, name",
  "where":[
    ["id","null"]
  ]
}

对于值列表

{
  "from": "users",
  "rows": "id, name",
  "where":[
    ["id","in",[1,2,3]]
  ]
}

如果您想使用这些操作符来否定搜索,只需在 between、null 和 in 操作符前添加字符 !

{
  "from": "users",
  "rows": "id, name",
  "where":[
    ["id","!null"],
	 ["id","!in",[1,2,3]],
	  ["id","!between","1|10"] 
  ]
}

现在,如果您在行中声明了一个聚合方法并想过滤聚合,可以使用以下方式的 having 子句

{
  "from": "users",
  "rows": "id, name, $count(*) as total",
  "group": "id, name",
  "having": [
    ["total", ">", "10"]
  ]
}

您也可以使用 order 子句对报告进行排序。以下是两个示例:按列降序排序

{
  "from": "users",
  "order": "id,desc"
}

按多列排序,其中第一列按降序排序,第二列按升序排序

{
  "from": "users",
  "order": ["id,desc","name"]
}

QJS 中的实体连接功能与 SQL 中的 JOIN 相似,使用三个基本方法。基于集合理论,可以使用 "join" 方法进行完全连接,当两个实体之间存在引用时;"left",当优先考虑左表时;以及 "right",当优先考虑右表时。

{
  "from": "users",
  "rows":"users.id,users.name,categories.name as category",
  "join":"categories,categories.id,users.category_id"
}

要执行多个连接,请遵循以下语法

{
  "from": "users",
  "rows": "users.id, users.name, categories.name as category",
  "left": [
    "categories, categories.id, users.category_id",
    "drivers, drivers.id, users.driver_id"
  ]
}

或者,您可以使用以下结构

{
  "from": "users",
  "rows": "users.id, users.name, categories.name as category",
  "left": [
    ["categories", "categories.id", "users.category_id"],
    ["drivers", "drivers.id", "users.driver_id"]
  ]
}