ans-group/laravel-sieve

一个用于过滤Eloquent查询的库

v0.11.2 2023-03-30 10:05 UTC

README

UKFast Logo

Laravel Sieve

用于处理API过滤和排序的库

例如,/pets?name:in=Snoopy,Hobbes这样的过滤器将应用于查询构建器实例,并且只有符合该条件的查询结果会返回

安装

首先,使用composer按照以下要求安装包

composer require ans-group/laravel-sieve

在Laravel中,服务提供器将自动发现。

如果你使用Lumen,你需要在bootstrap/app.php的"注册服务提供器"部分注册服务提供器

$app->register(UKFast\Sieve\SieveServiceProvider::class);

使用方法

Sieve使用表达式API来配置这些过滤器

<?php

class Pet extends Model implements Searchable
{
    public function sieve(Sieve $sieve)
    {
        $sieve->configure(fn ($filter) => [
           'name' => $filter->string(),
           'breed' => $filter->enum(['Beagle', 'Tiger']),
        ]);
    }
}
<?php

class PetController extends Controller
{
    public function index()
    {
        return Pets::query()->search()->paginate();
    }
}

过滤器

过滤器在查询参数中使用属性:操作符=术语的格式完成,例如

  • name:eq=Bob - WHERE name = 'Bob'
  • age:lt=20 - WHERE age < 20
  • employed:eq=true - WHERE employed = 1

默认情况下,如果没有指定操作符,则将默认为eq,因此name=Bob将展开为name:eq=Bob

类似与不类似

字符串过滤器也支持类似和不等操作符。要使用这些操作符,您应该使用*作为通配符,而不是典型数据库查询中使用的%

例如,first_name:lk=Sam*将匹配SamSamuelSamantha

排序

在设置模型时,您可以设置可排序的字段。
您可以将字段数组作为configure方法的第二个参数传递。
它不必匹配可过滤的字段,从而实现完全控制。

<?php

class Pet extends Model implements Searchable
{
    public function sieve(Sieve $sieve)
    {
        $sieve->configure(fn ($filter) => [
             'name' => $filter->string(),
             'breed' => $filter->enum(['Beagle', 'Tiger']),
          ],
          ['name']       
        );
    }
}

Sieve还将允许API的用户指定排序顺序。您可以通过sort=属性:方向来实现这一点

  • sort=age:asc
  • sort=id:desc

如果您没有指定方向(例如,sort=age),则排序将按升序进行。

您可以将多个列作为逗号分隔的列表指定为排序依据。它们将按照给出的顺序应用。例如,sort=age:asc,name:asc将按年龄排序,然后按字母顺序排序。

默认情况下,MySQL将按升序排序的第一个值为null,按降序排序的最后一个值为null。根据列的上下文,这可能不是期望的功能。您可以使用以下URL查询来更改此功能

  • sort=priority:asc_nulls_last
  • sort=priority:desc_nulls_first

您可以使用Sieve类的setDefaultSort设置默认排序。默认排序使用数据库列名而不是映射属性名,这意味着您可以使用默认排序属性而无需设置映射。

$sieve->setDefaultSort('name', 'asc')

可用过滤器

字符串

基本过滤器。适用于文本数据,实现了eqneqinninlknlk

<?php
$filter->string()

数字

适用于数字数据,除了基本运算符外,还提供了lt(小于)和gt(大于)

<?php
$filter->numeric()

枚举

与字符串过滤器相同,但增加了额外验证。如果用户提供了无效值,将抛出异常

<?php
$filter->enum(['HR', 'RnD'])

布尔值

仅提供eqneq。还接受两个参数来指定数据库中的true和false值

<?php
$filter->boolean() // defaults to 1 and 0
$filter->boolean('Yes', 'No') // search for Yes and No in the database

日期

提供与数字相同的操作

<?php
$filter->date(),

您可以通过在configure方法中使用FilterBuilder来获取这些过滤器的类型提示

<?php
$sieve->configure(fn (FilterBuilder $filter) [
    'name' => $filter->string(),
]);

关系

您可以使用过滤器构建器的for方法对关系进行过滤

<?php
$sieve->configure(fn ($filter) => [
    'owner_name' => $filter->for('owner.name')->string()
])

如果您的API属性与数据库中的列名不匹配,您也可以使用for方法,例如:

<?php
$sieve->configure(fn ($filter) => [
    'date_created' => $filter->for('created_at')->date()
])

包装过滤器

您可以轻松地包装所有可用的过滤器来装饰其行为。一个很好的例子是,如果您的API有一些计算属性

一个非常简单的例子可能是,您有一个存储在数据库中以便士为单位的price属性,但在API中以英镑显示(不一定是一个好的做法,但适用于本例)

我们仍然可以通过设置一个包装器来过滤这个,该包装器将在将查询传递给过滤器之前修改消费者查询

<?php

class PenceFilter implements WrapsFilter
{
    protected $filter;

    public function setFilter($filter)
    {
        $this->filter = $filter;
    }

    public function modifyQuery($query, SearchTerm $search)
    {
        $pence = $search->term() * 100;
         // will do a better API for making new search terms later
        $newTerm = new SearchTerm($search->property(), $search->operator(), $search->column(), $pence);

        $this->filter->modifyQuery($query, $search);
    }

    public function operators()
    {
        return $this->filter->operators();
    }
}

可以通过以下方式使用它

$sieve->configure(fn ($filter) => [
    'price' => $filter->wrap(new PenceFilter)->numeric(),
])

现在当用户搜索price:eq=1.50时,数据库查询将改为WHERE price = 150

需要注意的是,wrap可以被多次调用,并且构建器将反复重新包装

贡献

我们欢迎对这个包的贡献,这将有利于社区。

您可以通过open-source@ukfast.co.uk联系我们的开源团队,他们将在尽可能短的时间内回复您。

有关更多信息,请参阅我们的CONTRIBUTING文件。

安全

如果您认为您已经识别到一个安全漏洞,请通过security@ukfast.co.uk联系我们的团队,他们将在尽可能短的时间内回复您,而不是使用问题跟踪器。

许可证

本项目根据MIT许可证(MIT)授权。有关更多信息,请参阅许可证文件。