plokko / resource-query
Requires
- php: >=7.2
- ext-json: *
- illuminate/support: >=5.4.0
README
使用Ajax功能的Laravel查询的自动过滤和排序。
该软件包的范围
此软件包添加了帮助自动化创建后端定义的用户查询(Ajax)的类,具有高级功能,如过滤、排序、分页、资源铸造和智能铸造。查询将基于预定义的Eloquent查询,用户可以通过应用预定义的查询参数来自定义查询。所有查询参数都易于在后台定义和自定义,从而可以严格控制用户可以看到或执行的内容。
安装
使用composer安装它 composer require plokko/resource-query
初始化
要使用此类,您必须扩展基本 ResourceQuery
类或使用构建器。如果您打算重用相同的设置,则扩展 ResourceQuery
类是首选,如果您打算一次性使用它,则构建器方法更快。
扩展ResourceQuery
创建一个新的类,它扩展 plokko\ResourceQuery\ResourceQuery
并实现返回基础查询的 getQuery()
函数
use plokko\ResourceQuery\ResourceQuery; class ExampleResourceQuery extends ResourceQuery{ protected function getQuery():Builder { // Return the base query return MyModel::select('id','a','b') ->where('fixed_condition',1); } }
使用构建器
或通过定义 ResourceQueryBuilder
use plokko\ResourceQuery\ResourceQueryBuilder; $query = MyModel::select('id','etc'); //Add the base query $resource = new ResourceQueryBuilder($query);
示例用法
class MyController extends Controller { //... public function example1(Request $request){ $resource = new ExampleResourceQuery(); if($request->ajax()){ return $resource; } view('example',compact('resource')); } public function example2(Request $request){ $query = MyModel::select('id','etc'); $resource = new ResourceQueryBuilder($query); if($request->ajax()){ return $resource; } view('example',compact('resource')); } //... }
添加过滤器
过滤器由一个过滤器名称(与过滤器相关联的请求查询参数)、一个用于解析过滤器的条件以及一个(可选的)字段名称组成,用于指定要应用过滤器的表字段。
条件可以是基本查询条件(如 =
、!=
、<>
、like
、in
等),也可以是简写助手如 like%
、%like
或 %like%
,它们将在输入的前后或两端添加 "%" 字符,或者是一个Callable函数,它将解析过滤器。Callable过滤器将传递3个参数:0. \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder 查询 - 在其中应用过滤器的查询
- mixed $value - 被过滤的值
- FilterCondition $condition - 当前条件,用于检索条件或字段名称等。
您可以通过多种方式添加过滤器
// With the add function (default) $resource->filters->add(<FILTER_NAME:string>,[<CONDITION:string|callable>],[<FIELD_NAME:string>]); // Called as a parameter $resource->filters-><FILTER_NAME>; // Accessed as an array $resource->filters['<FILTER_NAME>']; // Called as a function $resource->filters-><FILTER_NAME>([<CONDITION:string|callable>],[<FIELD_NAME:string>]);
您还可以使用 condition
或 field
函数定义或修改过滤器条件或字段名称,例如
$resource->filters->add('filter1')->condition('=')->field('fieldA'); $resource->filters->filter2->condition('like')->field('fieldB');
您可以使用以下方式删除过滤器
$resource->filters->remove('<FILTER_NAME>');
或使用unset函数
unset($resource->filters['<FILTER_NAME>']);
如果您想删除所有过滤器,请使用 php $resource->removeFilters();
过滤器定义
过滤器可以在类初始化期间添加(如果扩展ResourceQuery)
class MyClassResource extends ResourceQuery{ //... function __construct() { //Remember to call parent constructor for inizialization parent::__construct(); // Adding filters $this->filter('filter1','=','fieldA'); $this->filter('filter2','like','fieldB'); //... } //... }
或通过直接调用资源
$query = MyModel::select('id','etc'); $resource = new ResourceQueryBuilder($query); // Note: this works also with already defined classes by adding or replacing existing filters // Ex. replace lines above with: $resource = new ExampleResourceQuery(); $resource->filters->add('filter1','=','fieldA'); $resource->filters->add('filter2','like','fieldB');
过滤器根名称
如果您想将所有过滤器封装在一个数组中(例如:“url?filter[filter-name]=value”),您可以使用 setFiltersRoot
定义它
$resource->setFiltersRoot('filter');//<-- 'filter' will be used as the root query parameter
或在类定义中设置 $filtersRoot
class ExampleResourceQuery extends ResourceQuery{ protected $filtersRoot = 'filter'; //... }
其他过滤器规则
默认过滤器值
如果您想在字段不存在时应用默认值,请使用 defaultValue 函数
$resource->filters->add('filter1','=','fieldA')->defaultValue('1234');//If filter "filter1" is not set it will be applied with value "123"
值格式化
如果您想在应用过滤器之前格式化过滤器值(例如,转义字符、大写等),请使用 formatValue
函数添加Callable函数。原始过滤器值将作为参数传递,并使用返回值作为新的过滤器值。
示例
$resource->filters->add('filter1','=','fieldA')->formatValue(function($value){ return trim($value); });
仅当存在另一个过滤器时才应用
如果您只想在有其他过滤器存在的情况下应用过滤器,可以使用applyIfPresent
函数。
$resource->filters->add('filter1','=','fieldA'); $resource->filters->add('filter2','like','fieldB'); // If fitler1 or filter2 are empty fitler3 will be ignored $resource->filters->add('filter3','=','fieldC')->applyIfPresent('filter1','filter2');
只在另一个过滤器不存在时应用。
如果您只想在有其他过滤器不存在的情况下应用过滤器,可以使用applyIfNotPresent
函数。
$resource->filters->add('filter1','=','fieldA'); $resource->filters->add('filter2','like','fieldB'); // If fitler1 or filter2 are not empty fitler3 will be ignored $resource->filters->add('filter3','=','fieldC')->applyIfNotPresent('filter1','filter2');
排序
与过滤类似,您可以通过多种方式声明排序查询参数,使用OrderBy
参数。
$resource->orderBy->add('<SORTING_PARAMETER>'[,<FIELD>][,<DIRECTION>]); $resource->orderBy-><SORTING_PARAMETER>; $resource->orderBy['<SORTING_PARAMETER>']; $resource->orderBy-><SORTING_PARAMETER>([,<FIELD>][,<DIRECTION>]);
对于每个过滤器,您可以指定一个相关表字段进行排序,使用field('<FIELD>')
函数,以及一个默认排序方向,使用defaultOrder('<DIRECTION>')
。如果您想使排序方向固定且不可由用户修改,可以使用direction('<DIRECTION>')
方法。
如果您想自定义排序,可以将回调函数作为field
参数传递;将要应用排序的查询将被作为第一个参数传递,排序方向作为第二个参数。
示例
$resource->orderBy->email->field('email'); $resource->orderBy->name->field('username')->defaultOrder('desc'); // Forced ascending $resource->orderBy->add('name-asc','username','asc'); // Example custom filter $resource->orderBy->test1->field(function($query,$direction){ $query->orderBy('email',$direction) ->orderBy('name',$direction) ->orderBy('id','asc'); });
默认排序顺序
如果您想指定默认排序顺序,您可以:
排序查询参数
过滤器查询参数可以通过ResourceQuery的$orderField
参数设置。过滤器可以作为键值对指定,排序参数作为键,方向作为值,或者使用两种简写语法之一(作为字符串,逗号分隔)。
<sorting_parameter>[:<direction>]
[+|-]<sorting_parameter>
,其中前置"+"表示升序,"-"表示降序。
示例
page?order_by[field1]=&order_by[field2]=asc&order_by[field3]=desc
或者
page?order_by=field1,field2:asc,field3:desc
或者
page?order_by=field1,+field2,-field3
JavaScript API
该包包括一个JavaScript对应版本,以帮助查询后端;由于它与PHP实现紧密相关,因此该包与composer包一起分发,而不是作为单独的npm包。
将其包含在resources/js/app.js
中。
import ResourceQuery from "../../vendors/plokko/resource-query/js/ResourceQuery"; // Make it available in pages window.ResourceQuery = ResourceQuery; //...
注意:Axios是一个必需的依赖项。
用法
通过指定目标URL和方法(默认为get)来创建一个新的ResourceQuery实例。
let rq = new ResourceQuery('/url','get');
后端应该是以下形式:
class MyController extends Controller { //... function testPage(Request $request){ $resource = new UserResourceQuery(); //...add filters, etc. // if it's an Ajax resource return the resource directly if($request->ajax()){ return $resource; } // Or else return the HTML page return view('mypage'); } //... }
您可以添加或修改过滤器、排序和选项。
// Set filters root parameter (must be the same as the back-end) rq.filtersRoot = 'filters'; // Set orderby parameter (must be the same as the back-end) rq.orderField = 'order_by'; // Add a filter rq.filters.test1 = 'a'; // or rq.filter('test1','a'); // or rq.addFilters({test1:'a',test2:'b'}); // Order rq.order_by = ['field1',['field2','desc']]; // or rq.orderBy('field1','asc'); // Clears all the filters rq.clearFilters(); // Clears all the orderby options rq.clearOrderBy(); //Clears all the filters and orderby options rq.resetQuery(); // Set page (if pagination is enabled) rq.page = 2; // Set the page size (may be ignored by the back-end if not allowed) rq.pageSize = 10; // 10 element per page
请求取消和选项
支持通过token选项进行请求取消。
let rq = new ResourceQuery('/url','get'); let cancelToken = ResourceQuery.cancelToken; rq.get({cancelToken}) .then(r => { console.log('Data received',r); }) .catch(e => { // Check if the request was user-cancelled if (ResourceQuery.isCancel(e)) { //the request was user-cancelled, no error thrown console.warn('user cancelled'); } else { console.error('Request error:', e); } }); //... // When you want to cancel the request cancelcancelToken.cancel();
有关其他支持配置选项的详细信息,请参阅Axios请求配置(某些属性可能被忽略)。