lachlanhickey/laravel-filterable

使用URL查询字符串来过滤Eloquent查询。

dev-L7 2024-06-03 03:45 UTC

This package is auto-updated.

Last update: 2024-10-03 04:34:55 UTC


README

Latest Version on Packagist Build Status Total Downloads

此包允许您通过查询字符串轻松处理数据库过滤。该想法来自Jeffrey的视频之一(付费墙后)。一个快速示例可能如下所示:/users?filter-username=~joe 将导致SQL查询 select * from users where "username" like '%joe%'

安装

您可以通过composer安装此包

composer require kyslik/laravel-filterable

如果您正在使用Laravel 7

composer require kyslik/laravel-filterable dev-L7

Laravel会自动发现此包。如果您想使用老方法,请禁用自动发现,并将 Kyslik\LaravelFilterable\FilterableServiceProvider::class 添加到您的 config/app.php 中的提供者数组。

您可以通过运行以下artisan命令来继续发布配置 php artisan vendor:publish

简介

此包允许您创建并应用两种类型的过滤器: 自定义通用

自定义过滤器

自定义 过滤器与Jeffrey的视频中的过滤器类似。您在一个构建器实例上定义逻辑,然后包通过 局部作用域 应用它。

假设一个产品需要显示最近创建的记录。您在过滤器类中创建一个方法 recent($minutes = null),它返回Builder实例

public function recent($minutes = null): \Illuminate\Database\Eloquent\Builder
{
    $minutes = (is_numeric($minutes)) ? $minutes : 30;

    return $this->builder->where('created_at', '>=', Carbon\Carbon::now()->subMinutes($minutes));
}

注意:完整的示例稍后展示

通用过滤器

通用 过滤器是在 配置文件 中定义的。默认情况下,此包支持过滤 timestampsrangesinsbooleansstrings

/?filter-created_at=t>=1510952444
/?filter-id=><1,19
/?filter-id=i=1,5,10,12
/?filter-admin=b=yes
/?filter-username=joe
/?filter-username=~joe
/?filter-username=~joe&filter-admin=b=yes&filter-created_at=t=1510952444

通用过滤器的默认操作矩阵

使用方法

当使用 自定义通用 过滤器时,您必须

  1. 在模型上具有 局部作用域,其签名是 scopeFilter(Builder $query, FILTERNAME $filters)
  2. 具有特定的(FILTERNAME)过滤器类,该类扩展了以下之一
    • Kyslik\LaravelFilterable\Generic\Filter 类 - 允许使用 自定义通用 过滤器
    • Kyslik\LaravelFilterable\Filter 类 - 仅允许使用 自定义 过滤器
  3. 在控制器中调用作用域

make:filter 命令

您可以使用以下命令创建新的过滤器。

php artisan make:filter SomeFilter

这将创建一个新 自定义 过滤器在 app/Filters 目录中。要创建 通用 过滤器,只需将 --generic-g)标志添加到命令中

php artisan make:filter SomeGenericFilter -g

最后,您可以通过更改 namespace 配置值来覆盖默认命名空间,例如

config/filterable.php

return [
    'namespace' => 'Http\Filters',
    ...
];

自定义过滤器的示例

假设您想在 User 模型上使用可过滤的,您将需要创建过滤器类 App/Filters/UserFilter.php(使用 php artisan make:filter UserFilter),指定 filterMap()filter 方法(recent(...))并使用自定义逻辑。

<?php
namespace App\Filters;

use Kyslik\LaravelFilterable\Filter;

class UserFilter extends Filter
{
    public function filterMap(): array
    {
        return ['recent' => ['recently', 'recent']];
    }

    public function recent($minutes = null)
    {
        $minutes = (is_numeric($minutes)) ? $minutes : 30;

        return $this->builder->where('created_at', '>=', \Carbon\Carbon::now()->subMinutes($minutes)->toDateTimeString());
    }
}

注意filterMap() 应返回一个关联数组,其中 是方法名,而 是别名或别名数组

现在通过 Filterable局部作用域 添加到 User 模型

use Kyslik\LaravelFilterable\Filterable;

...
class User extends Model
{
    use Filterable;
    ...
}

最后,在控制器中调用作用域,如下所示:

use App\Filters\UserFilter;
...
public function index(User $user, UserFilter $filters)
{
    return $user->filter($filters)->paginate();
}

现在,最终用户可以访问 users?recentusers?recentlyusers?recent=25,结果将通过在 UserFilter 类中定义的 recent() 方法进行过滤。

带有泛型过滤器的示例

假设您想在 User 模型上使用泛型过滤器。您必须创建过滤器类 App/Filters/UserFilter.php (使用 php artisan make:filter UserFilter -g 命令创建),并指定如下 $filterables

<?php
namespace App\Filters;

use Kyslik\LaravelFilterable\Generic\Filter;

class UserFilter extends Filter
{
    protected $filterables = ['id', 'username', 'email', 'created_at', 'updated_at'];
}

接下来,您必须通过 局部作用域User 模型与 Filterable 结合起来。

use Kyslik\LaravelFilterable\Filterable;

...
class User extends Model
{
    use Filterable;
    ...
}

最后,在控制器中调用作用域,如下所示:

use App\Filters\UserFilter;
...
public function index(User $user, UserFilter $filters)
{
    return $user->filter($filters)->paginate();
}

现在,您可以开始过滤 User 模型了。

注意:在幕后,...\Generic\Filter 类扩展了 Filter 类,因此使用 ...\Generic\Filter 也允许您应用过滤器类中定义的自定义过滤器。

额外配置

在使用泛型过滤器时,您可以定义哪些泛型应该被允许。在过滤器类中定义 settings() 方法,如下所示:

use Kyslik\LaravelFilterable\Generic\Filter
...
class UserFilter extends Filter
{
    protected $filterables = ['id', 'username', 'email', 'created_at', 'updated_at'];

    protected function settings()
    {
        // global settings for this filter, pick either "except" or "only" logic
        $this->only(['=', '~', '!~']);
        // $this->except(['!=']);

        // settings applied only to some columns, these settings ignore the "global" settings above
        $this->for(['username', 'id'])->only(['!=', '>=', '=', '~']);
        $this->for(['id'])->only(['=', '!=', '~']); // settings for "id" will be re-written
    }
}

额外功能

默认过滤

如果您需要在尚未应用过滤器的情况下应用过滤器(通过请求中包含的查询字符串确定),您可以在控制器中使用以下代码:

public function index(User $user, UserFilter $filter)
{
    // will redirect and "apply" the `recent` and `filter-id` filters 
    // if not a single filter from UserFilter is applied
    $filter->default(['recent' => now()->toDateTimeString(), 'filter-id' => '!=5']);

    return $user->filter($filter)->paginate();
}

最终用户将从 http://filters.test/users 重定向到 http://filters.test/users?recent=2018-10-01 13:52:40&filter-id=!=5。如果指定的 默认 过滤器不存在,将抛出 Kyslik\LaravelFilterable\Exceptions\InvalidArgumentException

注意:请小心避免 无限重定向

您可以在 原始问题 #10 中了解更多关于此功能的信息。

过滤器支持

待定

您可以在 原始 PR #9 中了解更多关于此功能的信息。

测试

composer test

变更日志

请参阅 CHANGELOG 了解最近有哪些变化。

贡献

请参阅 CONTRIBUTING 了解详情。

安全

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

致谢

许可

MIT 许可证 (MIT)。请参阅 许可文件 了解更多信息。