amirhshokri/laravel-filterable

为Laravel查询构建器添加过滤功能的更好解决方案。

v1.0.0 2024-09-09 21:12 UTC

This package is auto-updated.

Last update: 2024-09-12 09:21:08 UTC


README

简介

Laravel Filterable 帮助您将高效的过滤逻辑添加到Laravel查询构建器。您可以使用默认的过滤逻辑,手动定义自定义过滤逻辑,或使用提供的命令在任何路径下创建它。通过启用自动发现模式,该包将自动为您定位所需的过滤类。

安装

您可以通过composer安装此包

composer require amirhshokri/laravel-filterable

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="laravel-filterable-config"

这是已发布的配置文件的内容

return [
    'auto_discovery' => false,
    'namespace' => 'App\\Filterable\\Custom',
    'suffix' => 'Filter',
];

这些参数的用法将在下面讨论。

基本用法

步骤 1: 将 Filterable 特性添加到您的模型中

use Amirhshokri\LaravelFilterable\Main\Filterable;

class User extends Authenticatable
{
    use Filterable;
}

您还可以使用 $allowedFilterParameters 数组指定允许过滤的字段

use Amirhshokri\LaravelFilterable\Main\Filterable;

class User extends Authenticatable
{
    use Filterable;
    
    protected array $allowedFilterParameters = ["id", "email"];
}

如果未定义 $allowedFilterParameters,则所有参数都将允许进行过滤。

步骤 2: 将 filter() 方法添加到您的查询构建器中

$users = \App\Models\User::query()
   ->filter()
   ->get();

步骤 3: 提交请求

{
  "filters": [
    {
      "name": "id",
      "operator": "isEqualTo",
      "value": 1
    },
    {
      "name": "email",
      "operator": "contains",
      "value": "@gmail"
    }
  ]
}

支持的运算符

可用的运算符有

  • isEqualTo
  • isNotEqualTo
  • greaterThan
  • lessThan
  • greaterThanOrEqualTo
  • lessThanOrEqualTo
  • between
  • in
  • contains

深入探讨 filter() 方法

使用 filter() 方法有几种方法

方法 1: 传递自定义过滤类

您可以将自定义过滤类传递给 filter() 方法,为您的模型强制执行特定的过滤逻辑

$users = \App\Models\User::query()
   ->filter(new UserFilter())
   ->get();

如何创建自定义过滤类?

您可以选择手动创建自定义过滤类,或使用以下命令生成

php artisan make:filter <FilterName> --path=Path\To\Filter\Class

注意

  • 此命令使用配置文件中的 suffix 参数来创建过滤类。文件名必须以指定的后缀结尾(例如,MyNewUserFilter)。

  • 如果没有提供 --path 选项,则将使用配置文件中的 namespace 参数作为默认路径。

生成自定义过滤类的示例

use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;

class UserFilter extends CustomFilter
{
    //TODO: Add your custom filter logic here.
}

一旦您创建了自定义过滤类,您可以为希望过滤的每个字段扩展过滤逻辑。在自定义过滤类中添加一个与请求体中的 name 字段对应的函数

use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;

class UserFilter extends CustomFilter
{
    public function id($value, string $operator): void
    {
        //Custom filter logic for 'id' column
    }
    
    public function email($value, string $operator): void
    {
        //Custom filter logic for 'email' column
    }
}

注意

  • 每个函数可以接受 $value$operator 参数。 $value 代表请求中的值,$operator 代表运算符。

  • 使用 operatorMapper() 方法将运算符映射到数据库等效项,例如

  • $eloquentBuilder 属性在自定义过滤类中提供,允许更易于阅读的查询。它本质上是对Laravel默认查询构建器的副本。
use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;

class UserFilter extends CustomFilter
{
    public function id($value): void
    {
        $this->eloquentBuilder->where('id', $value);
    }
    
    public function mobile($value, string $operator): void
    {
        $this->eloquentBuilder->where('mobile', $this->operatorMapper($operator), $value);
    }
}

嵌套过滤

对于更复杂的过滤场景,您可以在另一个 filter() 调用内部调用 filter(),以应用多个条件,例如根据帖子标题过滤用户。

注意

  • 此外,请确保已将 Filterable 特性添加到 Post 模型中。
use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;

class UserFilter extends CustomFilter
{
    public function title($value, string $operator): void
    {
        $this->eloquentBuilder->whereHas('posts', function ($query) use ($value, $operator) {
            $query->setFilterParameters([
                    ["title", $operator, $value]
                ])->filter();
        });
    }
}

然后,提交请求

{
  "filters": [
    {
      "name": "title",
      "operator": "contains",
      "value": "pizza"
    }
  ]
}

注意

  • 您可以使用 OperatorEnum 添加多个条件,如下所示
use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;
use Amirhshokri\LaravelFilterable\Main\Filter\Enum\OperatorEnum;

class UserFilter extends CustomFilter
{
    public function title($value, string $operator): void
    {
        $this->eloquentBuilder->whereHas('posts', function ($query) use ($value, $operator) {
            $query->setFilterParameters([
                    ["id", OperatorEnum::IS_NOT_EQUAL_TO, 10],
                    ["title", $operator, $value],
                    ["slug", OperatorEnum::CONTAINS, 'another pizza']
                ])->filter();
        });
    }
}

方法 2: 使用自动发现

该包包含一个自动发现功能,根据配置文件中定义的 namespacesuffix 参数自动检测自定义过滤类。此功能在您希望不将自定义过滤类传递给 filter() 方法时很有用。

当启用 自动发现 时,它将搜索名为 {ModelName}{Suffix}.php 的过滤器类(例如,在 App\Filterable\Custom 中的 UserFilter.php)。如果自定义过滤器类未在预期位置找到,将抛出异常。

注意

  • 在本地启用或禁用自动发现:想象一下这样的场景,全局启用了自动发现,但你不想为某些 filter() 调用使用它,反之亦然。在这种情况下,你可以在调用 filter() 方法之前简单地调用 setFilterAutoDiscovery() 方法,传递一个布尔值。
use Amirhshokri\LaravelFilterable\Main\Filter\Custom\CustomFilter;

class UserFilter extends CustomFilter
{
    public function title($value, string $operator): void
    {
        $this->eloquentBuilder->whereHas('posts', function ($query) use ($value, $operator) {
            $query->setFilterParameters([
                    ["title", $operator, $value]
                ])
                ->setFilterAutoDiscovery(false)
                ->filter();
        });
    }
}
  • 如果你更喜欢使用 make:filter 命令创建自定义过滤器类,并且该类在自动发现模式下可被发现,你可以省略 --path 选项,自动在指定的 namespace 中生成文件。

方法 3:使用默认过滤器

如果你没有为 filter() 方法提供自定义过滤器类,并且自动发现被关闭,该包将使用之前在 基本用法 部分中解释的默认过滤器功能为你提供模型。

致谢

许可协议

MIT 许可协议(MIT)。有关更多信息,请参阅 许可文件