culturegr / filterer
为Eloquent模型添加筛选、排序和分页功能。
Requires
- php: ^8.1|^8.2|^8.3
- illuminate/support: ^9.0|^10.0|^11.0
Requires (Dev)
- laravel/legacy-factories: ^1.4
- mockery/mockery: ^1.6
- orchestra/testbench: ^8.26
- phpunit/phpunit: ^10.0
README
本包提供了一种简单的方法,可以将筛选、排序和分页功能添加到Eloquent模型中。
安装
通过Composer
$ composer require culturegr/filterer
用法
假设以下数据库架构
以下是对应于clients表的Client模型
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Client extends Model { protected $date = ['registered_at']; public function country() { return $this->belongsTo(Country::class); } public function orders() { return $this->hasMany(Order::class); } public function favoriteProducts() { return $this->belongsToMany(FavoriteProduct::class); } }
重要 Filterer包强烈依赖于Laravel命名约定来命名模型之间的关系。因此,为了使包按预期工作,定义的模型关系应按照这些约定命名
使用特性
可以通过使用Filterer包提供的Filterable特性将筛选、排序和分页功能添加到Client模型中
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use CultureGr\Filterer\Filterable; class Client extends Model { use Filterable; ... }
定义可筛选和可排序字段
可以显式定义可筛选和/或可排序的字段,分别使用模型上的fiterable和sortable属性。可筛选和可排序字段可以存在于模型本身或其一级关系上
- 存在于模型本身的字段使用列名定义,即
columnName - 存在于相关模型上的字段使用关系名后跟点
.和关联模型上的列名定义,即relationshipName.columnName
例如,为了能够同时按年龄、国家名称、订单项和收藏产品价格筛选和排序Client模型,必须定义以下可筛选和可排序字段
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use CultureGr\Filterer\Filterable; class Client extends Model { use Filterable; protected $filterable = ['age', 'country.name', 'orders.items', 'favoriteProducts.price']; protected $sortable = ['age', 'country.name', 'orders.items', 'favoriteProducts.price']; ... }
支持的数据类型和筛选操作符
以下表格列出了在筛选资源时可以执行的数据类型及其对应操作
筛选模型
可以使用(由Filterable特性提供的)filter方法获取筛选后的结果,并将包含具有filters属性的数组的参数传递给该方法,如下所示
Client::filter([ 'filter' => [ [ 'column' => <FILTERABLE>, 'operator' => <OPERATOR>, 'query_1' => <VALUE>, 'query_2' => null|<VALUE> // query_2 is required only with **between**, **not_between** and **between_date** operators ], ... ] ])->get();
重要:当作为参数传递一个具有
limit属性的参数时,filter方法返回一个Eloquent\Builder实例(请参阅分页模型)
例如,以下筛选可以应用于筛选年龄在35至40岁之间、来自希腊、在2020年5月1日至5月31日之间下订单、收藏产品价格低于10欧元的客户
- 按年龄,升序
- 按国家名称,降序
- 按订单中的项目数量,升序
- 按收藏产品的价格,降序
Client::filter([ 'filters' => [ [ 'column' => 'age', 'operator' => 'between', 'query_1' => '35', 'query_2' => '40' ], [ 'column' => 'country.name', 'operator' => 'equal_to', 'query_1' => 'Greece', 'query_2' => null ], [ 'column' => 'orders.shipped_at', 'operator' => 'between_date', 'query_1' => '2020-05-1', 'query_2' => '2020-05-31' ], [ 'column' => 'favoriteProducts.price', 'operator' => 'less_than', 'query_1' => '10', 'query_2' => null ], ], ])->get();
排序模型
可以使用filter方法获取排序后的结果,并将包含具有sorts属性的数组的参数传递给该方法,如下所示
Client::filter([ 'sort' => [ [ 'column' => <SORTABLE>, 'direction' => <asc|desc>, ], ... ] ])->get();
例如,以下排序可以应用于按以下方式排序客户
- 按年龄,升序
- 按国家名称,降序
- 按订单中的项目数量,升序
- 按收藏产品的价格,降序
Client::filter([ 'sorts' => [ [ 'column' => 'age', 'direction' => 'asc', ], [ 'column' => 'country.name', 'direction' => 'desc', ], [ 'column' => 'orders.items', 'direction' => 'asc', ], [ 'column' => 'favoriteProducts.price', 'direction' => 'desc', ], ] ])->get();
分页模型
可以使用filter方法获取分页后的结果,并将包含具有limit属性和page属性的数组的参数传递给该方法,如下所示
Client::filter([ 'limit' => <VALUE>, 'page' => <VALUE> ]);
重要: 当指定了
limit时,filter方法将返回一个LengthAwarePaginator实例。有关 Laravel 处理分页的更多信息,请参阅 这里
组合过滤、排序和分页
可以使用 Filterable 特性提供的 filter 方法结合过滤、排序和分页功能,并将包含任何三个 filters、sorts 以及 limit/page 属性的数组作为参数传递
Client::filter([ 'filter' => [ ... ], 'sort' => [ ... ], 'limit' => '...', 'page' => '...' ]);
查询字符串格式
可以通过解析以下格式的查询字符串来轻松获取 filter 方法的参数
GET http://example.com/clients
?filter[0][column]=<FILTERABLE>&filter[0][operator]=<OPERATOR>&filter[0][query_1]=<VALUE1>&filter[0][query_2]=<VALUE2>
&filter[1][column]=<FILTERABLE>&filter[0][operator]=in&filter[0][query_1][0]=<VALUE1>&filter[0][query_1][1]=<VALUE2>...
&filter[2][column]=...
&sort[0][column]=<SORTABLE>&sort[0][direction]=<DIECTION>
&sort[1][column]=...
&limit=<LIMIT>
&page=<PAGE>
测试
$ composer test
许可
请参阅 许可文件 获取更多信息。
致谢
- Code Kerala
- 出色的 Laravel/PHP 社区