henzeb/query-filter-builder

构建过滤器的一种优雅方式

v1.3.0 2024-03-11 13:32 UTC

This package is auto-updated.

Last update: 2024-09-11 14:28:06 UTC


README

Build Status Latest Version on Packagist Total Downloads Test Coverage

当您需要在API端点上的过滤器时,这个包为您提供了一个友好且简单的界面,允许您添加过滤器,而无需将成千上万个参数传递给您的函数或编写控制器内的SQL查询。

此包支持Laravel。如果您想为其他框架贡献力量,请参阅贡献指南

安装

您可以通过composer安装此包

composer require henzeb/query-filter-builder

用法

有关Laravel特定用法的详细信息,请参阅此处

在您的控制器中,您可以根据应用程序用户提供的参数构建类似的内容。

use Henzeb\Query\Filters\Query;

$filter = (new Query())
    ->nest(
        (new Query)
            ->nest(
                (new Query)
                    ->is('animal', 'cat')
                    ->less('age', 10)
            )->or()
            ->nest(
                (new Query)
                    ->is('animal', 'dog')
                    ->between('age', 5, 7)
            )
    )->in('disease', 'diabetes', 'diarrhea')
    ->limit(50)
    ->offset(50);

使用Laravel的查询构建器构建查询,可以这样做

use DB;
use Henzeb\Query\Illuminate\Builders\Builder;

$query = DB::table('patients')
    ->where('vet_id', 1);
    
$filter->build(new Builder($query));

这将导致以下查询

select *
from `patients`
where `vet_id` = ?
  and (
          (`animal` = ? and `age` < ?)
          or 
          (`animal` = ? and `age` between ? and ?)
      )
  and `disease` in (?, ?)
limit 50 offset 50

注意:查询过滤器不能以or开头。这可以防止数据泄露情况,例如获取所有自己的记录或另一个兽医的狗。

select * from `patients` where `vet_id` = ? or `animal` = ?

可能会获取所有自己的记录或另一个兽医的狗。

自定义过滤器

如果您需要特定功能,也可以创建自己的过滤器。

当使用Laravel构建时,您的自定义过滤器可能看起来像这样

use Henzeb\Query\Illuminate\Filters\Contracts\Filter;

use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder as IlluminateBuilder;

class OwnerCountFilter implements Filter
{
    public function __construct(private int $count)
    {
    }

    public function build(EloquentBuilder|IlluminateBuilder $builder): void
    {
        $builder->whereRaw(
            '(
                select count(1) 
                from `owners_patients` 
                where `owners_patients`.`patient_id` = `patients`.`id`
            ) = ?',
            [$this->count]
        );
    }
}

然后您可以这样调用它

use Henzeb\Query\Filters\Query;
use App\Filters\YourCustomFilter;

$filter = (new Query)->filter(OwnerCountFilter(1));

这将导致以下查询

select *
from `patients`
where `vet_id` = ?
  and (
            (
                select count(1) 
                from `owners_patients` 
                where `owners_patients`.`patient_id` = `patients`.`id`
            ) = ?
      )

创建自己的构建器。

只需实现Henzeb\Query\Builders\Contracts\QueryBuilder接口。

自定义过滤器

自定义过滤器的方法可能感觉有点奇怪。您必须创建自己的自定义过滤器接口,因为默认的Henzeb\Query\Illuminate\Filters\Contracts\Filter接口没有任何方法。

请参阅Henzeb\Query\Illuminate\Builders\Builder以获取代理示例,以便启用您的IDE的类型提示。

如果您有更好的方法,请告诉我或提交一个pull请求。

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

贡献

有关详细信息,请参阅贡献指南

安全

如果您发现任何安全问题,请通过电子邮件henzeberkheij@gmail.com而不是使用问题跟踪器。

鸣谢

许可

GNU AGPLv。有关更多信息,请参阅许可文件