ambengers/query-filter

Laravel 资源过滤包,用于通过请求查询字符串过滤模型

4.9.2 2023-09-01 04:06 UTC

This package is auto-updated.

Last update: 2024-08-30 01:09:07 UTC


README

此包提供了一种优雅的方式来通过请求查询字符串过滤 Eloquent 模型。

灵感来自 Laracasts

Build Status StyleCI

特性

此包允许您通过请求查询字符串创建过滤器。开箱即用,此包还提供对 Eloquent 模型的排序、分页和搜索功能。

安装

在终端中运行以下命令。

composer require ambengers/query-filter

然后通过运行以下命令发布配置文件。

php artisan vendor:publish --tag=query-filter-config

配置文件包含过滤类命名空间和路径的配置。默认命名空间为 App\Filters,默认路径为 app/Filters

使用方法

基于方法的过滤器

您可以使用 make:query-filter 命令生成过滤器类。

php artisan make:query-filter PostFilter

在过滤器类中,您还可以定义自己的自定义过滤器。例如,让我们添加一个过滤器 /posts?published 以获取仅发布过的帖子

use Ambengers\QueryFilter\AbstractQueryFilter;

class PostFilter extends AbstractQueryFilter
{
  /**
   * Filter the post to get the published ones
   *
   * @return Illuminate\Database\Eloquent\Builder
   */
  public function published()
  {
    return $this->builder->whereNotNull('published_at');
  }
}

现在,您可以在控制器中应用此过滤器。例如

use App\Filters\PostFilter;

class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index(PostFilter $filters)
  {
    $posts = Post::filter($filters);

    return PostResource::collection($posts);
  }
}

基于对象的过滤器

如果您更喜欢面向对象的方式来创建过滤器,您可以在 Filter 类中创建一个 $filters 数组来声明您的过滤器。

use Ambengers\QueryFilter\AbstractQueryFilter;

class PostFilter extends AbstractQueryFilter
{
  /**
   * List of filters.
   *
   * @var array
   */
  protected $filters = [
    'published' =>  \App\Filters\Published::class,
  ];
}

$filters 数组将接收一个键值对,其中键是查询字符串中的参数,值是处理过滤的过滤器对象。

然后您可以使用 make:query-filter-object 命令生成您的过滤器对象。注意:过滤器对象将使用与您的过滤器类相同的命名空间。

php artisan make:query-filter-object Published

过滤器对象是一个简单的可调用类,它接受 Eloquent\Builder 作为第一个参数,将查询字符串值作为第二个参数。在 invoke 方法中包含过滤逻辑,如下所示。

use Illuminate\Database\Eloquent\Builder;

class Published
{
  /**
   * Handle the filtering
   *
   * @param  Illuminate\Database\Eloquent\Builder $builder
   * @param  string|null  $value
   * @return Illuminate\Database\Eloquent\Builder
   */
  public function __invokable(Builder $builder, $value = null)
  {
    $builder->whereNotNull('published_at');
  }
}

排序

此包还允许您通过 field|direction 语法对模型进行排序。

/** Sorting */
/posts?sort=created_at|desc

分页

此包还允许您按照如下方式对模型进行分页。

/** Pagination */
/posts?page=2

在幕后,它使用 Laravel 的分页,默认的 per_page 大小为 15。当然,您可以像这样覆盖此行为。

/** Pagination */
/posts?page=2&per_page=10

注意:如果请求查询字符串中不存在分页键,则将返回一个集合结果。

搜索

此包还允许您定义可搜索的列。默认情况下,当您使用 make:query-filter 命令生成过滤器类时,该类将包含一个 $searchableColumns 数组。然后,在此数组中列出您模型的可搜索列。

class PostFilter extends AbstractQueryFilter
{
  /**
   * List of searchable columns
   *
   * @var array
   */
  protected $searchableColumns = ['subject', 'body'];
}

可搜索的关系列

如果要让模型通过关系字段进行搜索,则 $searchableColumns 可以接受一个键值对。

class PostFilter extends AbstractQueryFilter
{
  /**
   * List of searchable columns
   *
   * @var array
   */
  protected $searchableColumns = [
    'subject',
    'body',
    'comments' => ['body'],
  ];
}

可加载的关系

此包允许您使用查询字符串加载模型的关联关系。首先,使用 make:query-loader 命令创建您的加载类。

php artisan make:query-loader PostLoader

然后,在过滤器类中声明加载类。

use App\Loaders\PostLoader;

class PostFilter extends AbstractQueryFilter
{
  /**
   * Loader class
   *
   * @var string
   */
   protected $loader = PostLoader::class;
}

然后在加载类中,在 $loadables 数组中声明可以预加载/延迟加载的关联关系。

class PostLoader extends AbstractQueryLoader
{
    /**
     * Relationships that can be lazy/eager loaded
     *
     * @var array
     */
    protected $loadables = [
        'comments', 'author'
    ];
}

就这样!现在在您的查询字符串中使用 load 参数来加载关联关系。

/posts?load=comments,author

注意:在$loadables数组中,可以使用驼峰式或蛇形命名法来声明多词关系的实体。该包会自动将关系转换为蛇形命名法,这是您编写关系方法时通常使用的方式。另外,即使在使用查询字符串时,未在$loadables数组中声明的关联关系也不会进行延迟加载。

在控制器@show操作中使用Loader

Controller@show操作通常返回单个模型实例而不是集合。但是,有时您可能需要通过查询字符串来可选地加载关联关系。

将加载器类作为参数注入到您的show方法中,然后在您的对象上调用filter方法并传入加载器实例。

class PostController extends Controller
{
    /**
     * Display the specified resource.
     *
     * @param App\Models\Post $post
     * @param App\Loaders\PostLoader $loader
     * @return Illuminate\Http\JsonResponse
     */
    public function show(Post $post, PostLoader $loader)
    {
        $post = $post->filter($loader);

        return response()->json($post);
    }
}

现在您应该能够从查询字符串中加载您的关联关系了。

/posts/1?load=comments,author

包含软删除约束

当使用管道符号请求延迟加载的模型时,请包含软删除约束。

/posts/1?load=comments|withTrashed // comments will include soft deleted models
/posts/1?load=comments|onlyTrashed // comments will include only soft deleted models

防止方法名冲突

要自定义在模型上调用以使用查询过滤器的方法名称,只需更新query_filter配置文件中的method键的值。

return [
    // The method to call to use the query filter
    'method' => 'fooBar', // Now call $post->fooBar($loaders)
...
]

Laravel Livewire一起使用

Livewire在向后端发送请求时遵循自己的结构。这使得查询过滤器包无法自动从请求查询字符串中读取参数。

然而,您仍然可以在运行时手动分配参数,通过从容器中解析查询过滤器类并设置parameters,如下所示...

public function render () {
    $filters = app(PostFilter::class)->parameters(['search' => 'foo']);

    $posts = Post::filter($filters);

    return view('livewire.posts.index', ['posts' => $posts]);
}

类似包

cerbero90/query-filters