emargareten / eloquent-filters
使用简单数组轻松为您的eloquent模型添加过滤器
Requires
- php: ^8.1
- illuminate/support: ^9.0|^10.0|^11.0
Requires (Dev)
- larastan/larastan: ^2.9.2
- laravel/pint: ^1.14.0
- nunomaduro/collision: ^7.10
- orchestra/testbench: ^8.21.1
- pestphp/pest: ^2.34.1
- phpstan/phpstan: ^1.10.60
- phpunit/phpunit: ^10.5.11
README
Eloquent Filterable是一个帮助您使用数组过滤Laravel Eloquent模型的包。使用此包,您可以根据不同的标准及其组合轻松过滤Eloquent模型。
需求
此包需要PHP 8.1或更高版本。
安装
您可以通过composer安装此包
composer require emargareten/eloquent-filters
用法
要开始使用,您需要将Emargareten\EloquentFilterable\Filterable
特征添加到您的模型中。此特征为您添加一个filter
方法,您可以使用它来过滤模型。
然后,在您的模型中添加一个名为filterTypes
的属性,它包含一个可过滤字段数组的列表。数组的键是可以过滤的字段的名称,值是应用于字段的过滤类型的名称。
use Emargareten\EloquentFilterable\Filterable; class User extends Model { use Filterable; public array $filterTypes = [ 'name' => 'string', 'email' => 'string', 'age' => 'number', 'created_at' => 'date', ]; }
过滤类型
以下过滤类型是默认可用的:string
、number
、boolean
、date
和time
。
每种类型都有一个相应的过滤类,用于过滤字段。例如,string
类型使用Emargareten\EloquentFilterable\Filters\StringFilter
类。
要创建自己的过滤类型或覆盖/扩展现有类型,您应该创建一个类,其中每个方法都是一个过滤操作符,方法名称应该是操作符名称(驼峰式),方法应接受3个参数:$query
、$property
和$value
。
namespace App\Filters; use Emargareten\EloquentFilterable\Filters\StringFilter as BaseStringFilter; class StringFilter extends BaseStringFilter { public function pattern(Builder $query, string $property, string $value): void { $query->where($property, 'REGEXP', $value); } public function notPattern(Builder $query, string $property, string $value): void { $query->where($property, 'NOT REGEXP', $value); } }
然后,在filter_types
配置选项中注册您的过滤类。(使用php artisan vendor:publish --provider="Emargareten\EloquentFilterable\EloquentFilterableServiceProvider"
发布文件)
return [ /* * The filter classes to be used for each type. */ 'filter_types' => [ - 'string' => \Emargareten\EloquentFilters\Filters\StringFilter::class, + 'string' => \App\Filters\StringFilter::class, 'number' => \Emargareten\EloquentFilters\Filters\NumberFilter::class, 'boolean' => \Emargareten\EloquentFilters\Filters\BooleanFilter::class, 'date' => \Emargareten\EloquentFilters\Filters\DateFilter::class, 'time' => \Emargareten\EloquentFilters\Filters\TimeFilter::class, ], ];
过滤
您可以通过在模型上调用filter
方法并传递一个过滤器数组来过滤模型。
每个过滤器由3个元素组成:property
、operator
和value
。
property
是应过滤的字段的名称,此字段必须在您的模型中定义在filterTypes
属性中(这可以防止SQL注入)。operator
是用于过滤字段的操作符(可以是您想要的任何大小写)。value
是用于过滤字段的值。
User::filter([ [ 'property' => 'name', 'operator' => 'equal', 'value' => 'John', ], [ 'property' => 'age', 'operator' => 'greater-than', 'value' => 18, ], ])->get();
您可以通过在操作符前加类型和冒号(:
)来覆盖默认操作符类型。例如,如果您想为年龄字段使用string
类型而不是number
类型,则可以使用string:starts-with
操作符。
如果您只有一个过滤器,则可以直接将过滤器传递给filter
方法,而不是传递过滤器数组。
User::filter([ 'property' => 'name', 'operator' => 'equal', 'value' => 'John', ])->get();
要使用OR
分组过滤器,可以将过滤器嵌套在额外的数组中。
User::filter([ [ 'property' => 'name', 'operator' => 'equal', 'value' => 'John', ], [ [ 'property' => 'age', 'operator' => 'less-than', 'value' => 18, ], [ 'property' => 'age', 'operator' => 'greater-than', 'value' => 60, ], ], ])->get();
上述示例将返回所有名为John的用户,他们要么年龄小于18岁,要么年龄大于60岁。
通过关系过滤
要通过对关系进行过滤,可以使用点表示法指定应过滤的关系和字段。
User::filter([ [ 'property' => 'posts.title', 'operator' => 'contains', 'value' => 'laravel', ], ])->get();
上述示例将返回所有拥有标题包含单词laravel的帖子的用户。
注意 要通过对关系进行过滤,必须在相关模型上使用
Filterable
特征。
可用操作符
字符串操作符
exists
- 字段值不为空。(可以省略value
参数)not-exists
- 字段值为空。(可以省略value
参数)equal
- 字段值等于筛选值。not-equal
- 字段值不等于筛选值。starts-with
- 字段值以筛选值开头。not-starts-with
- 字段值不以筛选值开头。ends-with
- 字段值以筛选值结尾。not-ends-with
- 字段值不以筛选值结尾。contains
- 字段值包含筛选值。not-contains
- 字段值不包含筛选值。in
- 字段值在筛选值中。(value
应该是一个数组)not-in
- 字段值不在筛选值中。(value
应该是一个数组)
数字运算符
exists
- 字段值不为空。(可以省略value
参数)not-exists
- 字段值为空。(可以省略value
参数)equal
- 字段值等于筛选值。not-equal
- 字段值不等于筛选值。greater-than
- 字段值大于筛选值。greater-than-or-equal
- 字段值大于或等于筛选值。less-than
- 字段值小于筛选值。less-than-or-equal
- 字段值小于或等于筛选值。between
- 字段值在筛选值之间。(value
应该是一个数组)not-between
- 字段值不在筛选值之间。(value
应该是一个数组)in
- 字段值在筛选值中。(value
应该是一个数组)not-in
- 字段值不在筛选值中。(value
应该是一个数组)
布尔运算符
exists
- 字段值不为空。(可以省略value
参数)not-exists
- 字段值为空。(可以省略value
参数)equal
- 字段值等于筛选值。not-equal
- 字段值不等于筛选值。
日期运算符
exists
- 字段值不为空。(可以省略value
参数)not-exists
- 字段值为空。(可以省略value
参数)equal
- 字段日期与筛选值相同。not-equal
- 字段日期不与筛选值相同。greater-than
- 字段日期晚于筛选值。greater-than-or-equal
- 字段日期晚于或等于筛选值。less-than
- 字段日期早于筛选值。less-than-or-equal
- 字段日期早于或等于筛选值。between
- 字段日期在筛选值日期之间。(value
应该是一个数组)not-between
- 字段日期不在筛选值日期之间。(value
应该是一个数组)
时间运算符
exists
- 字段值不为空。(可以省略value
参数)not-exists
- 字段值为空。(可以省略value
参数)equal
- 字段时间与筛选值相同。not-equal
- 字段时间不与筛选值相同。greater-than
- 字段时间晚于筛选值。greater-than-or-equal
- 字段时间晚于或等于筛选值。less-than
- 字段时间早于筛选值。less-than-or-equal
- 字段时间早于或等于筛选值。
动态自定义筛选
您可以通过向模型添加以 filter
为前缀的方法来定义动态筛选(类似于以 scope
为前缀的本地筛选)。
use Emargareten\EloquentFilters\Filterable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class Post extends Model { use Filterable; /** * Filter the query by posts that have at least 20 views. */ public function filterHasTwentyViews(Builder $query): void { $query->where('views', '>=', 20); } }
您还可以定义一个接受运算符和值的动态筛选
/** * Filter the query by posts that have at least the given amount of views. */ public function filterHasViews(Builder $query, string $operator, int $count): void { $query->where('views', $operator, $count); }
然后您可以在筛选数组中使用动态筛选
Post::filter([ [ 'property' => 'has-twenty-views', ], ])->get(); // using a value Post::filter([ [ 'property' => 'has-minimum-views', 'operator' => '>=', 'value' => 20, ], ])->get();
变更日志
请参阅 CHANGELOG 了解最近的变化。
测试
composer test
贡献
欢迎贡献!如果您发现任何错误或问题或有一个功能请求,请打开一个新的问题或提交一个拉取请求。在贡献之前,请确保阅读 贡献指南。
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。