ukfast/laravel-sieve

此包已被弃用且不再维护。作者建议使用 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();
    }
}

过滤器

过滤器在查询参数中使用格式 property:operator=term 进行,例如

  • 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=property:direction来做到这一点

  • 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。还接受两个参数来指定数据库中的真和假值

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

日期

提供与数值相同的操作

<?php
$filter->date(),

您可以通过在配置方法中使用 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)许可。有关更多信息,请参阅 许可证 文件。