emargareten/eloquent-filters

使用简单数组轻松为您的eloquent模型添加过滤器

v0.0.11 2024-03-18 15:18 UTC

README

Latest Version on Packagist Software License Tests Total Downloads

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',
    ];
}

过滤类型

以下过滤类型是默认可用的:stringnumberbooleandatetime

每种类型都有一个相应的过滤类,用于过滤字段。例如,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个元素组成:propertyoperatorvalue

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)。有关更多信息,请参阅 许可文件