thejano / laravel-filterable
为 Laravel 模型添加过滤功能
Requires
- php: ^8.1
- illuminate/contracts: ^10.0|^11.0
- phpdocumentor/type-resolver: ^1.5
- spatie/laravel-package-tools: ^1.9.0
- spatie/php-structure-discoverer: ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- nesbot/carbon: ^2.63
- nunomaduro/collision: ^7.10.0|^8.0.1
- orchestra/testbench: ^8.0|^9.0
- pestphp/pest: ^2.31
- pestphp/pest-plugin-laravel: ^2.0
- phpunit/phpunit: ^10.0
README
此软件包为 Laravel 模型添加过滤功能。它基于 Filterable 和 Query Filter 类。该软件包将提供生成 Filterable 和 Query Filter 类的命令。默认情况下,它将添加一些默认过滤功能,例如排序、获取两个日期之间的数据等。
想象一下,您有一个包含以下参数的 URL
/posts?slug=the-new-web&published=true&category=web-development&tags[]=web&tags[]=laravel&tags[]=flutter
Laravel 请求所有方法 request()->all()
将返回类似这样的结果
[ "slug" => "the-new-web", "published" => "true", "category" => "web-development", "tags" => [ "web", "laravel", "flutter"], ]
通常,您应该逐个执行逻辑以执行过滤
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Post; class PostController extends Controller { public function index(Request $request) { $query = Post::query(); if ($request->has('title')) { $query->where('title', 'LIKE', '%' . $request->input('title') . '%'); } if ($request->has('published')) { $query->where('published', (bool) $request->input('published')); } if ($request->has('category')){ $query->whereHas('category', function ($query) use ($request) { return $query->where('category_slug', $request->input('category')); }); } if ($request->has('tags')){ $query->whereHas('tag', function ($query) use ($request) { return $query->where('tag_slug', $request->input('tags')); }); } $posts = $query->get(); return view('posts',compact('posts')); } }
对于简单的查询,这很好,但当您有很多过滤器时,您无法控制它们,并且它们都不能重用。
使用此软件包,您只需要在返回记录之前将 filterable()
范围方法传递给您的模型,如下面的示例所示
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Post; class PostController extends Controller { public function index(Request $request) { $posts = Post::filterable()->get(); return view('posts',compact('posts')); } }
要求
该软件包需要
- PHP 8.1 或更高版本
- Laravel 10.x 或更高版本
安装
您可以通过 composer 安装此软件包
composer require thejano/laravel-filterable
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="filterable-config"
用法
要添加魔法,您只需将 hasFilterableTrait
添加到您的模型中。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use TheJano\LaravelFilterable\Traits\HasFilterableTrait; class Post extends Model { use HasFactory; use HasFilterableTrait; }
然后您需要创建一个 FilterableClass 和一些 Query Filters 以定义您的规则。
为了消除创建类的痛苦,我已经添加了一些命令。
- 要创建一个 Filterable 类,您需要运行此命令
php artisan make:filterable PostsFilterable
它将在 \App\Filters\Filterable\PostsFilterable
下生成一个类,并包含
<?php namespace App\Filters\Filterable; use TheJano\LaravelFilterable\Abstracts\FilterableAbstract; use TheJano\LaravelFilterable\Interfaces\FilterableInterface; class PostsFilterable extends FilterableAbstract implements FilterableInterface { /** * It contains list of Query Filters * * @var Array */ protected array $filters = []; }
- 现在让我们创建一个 Query Filter 类
php artisan make:query-filter PublishedQueryFilter
它将在 \App\Filters\QueryFilter\PublishedQueryFilter
下生成一个类,并包含
<?php namespace App\Filters\QueryFilter; use Illuminate\Database\Eloquent\Builder; use TheJano\LaravelFilterable\Abstracts\QueryFilterAbstract; use TheJano\LaravelFilterable\Interfaces\QueryFilterInterface; class PublishedQueryFilter extends QueryFilterAbstract implements QueryFilterInterface { /** * Can be used to map the values. * It can be returned through resolveValue method * * @var Array */ protected array $mapValues = []; /** * Handle The Query Filter * * * @param Builder $builder Query Builder * @param string $value * @return Builder **/ public function handle(Builder $builder, $value): Builder { return $builder; } }
您将在每个 Query Filter 中单独执行每个列的逻辑。让我们在这里实现逻辑
public function handle(Builder $builder, $value): Builder { return $builder->where('published', $value); }
返回值是一个字符串,它不返回任何数据。因此,我们应该映射值。
类中有一个 $mapValues
属性。
protected array $mapValues = [ 'true' => true, 'false' => false, ];
最后,我们应该通过 resolveValue()
方法解析映射的值。
protected array $mapValues = [ 'true' => true, 'false' => false, ]; public function handle(Builder $builder, $value): Builder { $value = $this->resolveValue($value); // return Builder if the value is null if (is_null($value)) { return $builder; } return $builder->where('published', $value); }
为了使 Query Filter 生效,我们应该将其附加到 PostsFilterable
类的 $columns
属性。
public array $filters = [ 'published' => 'App\\Filters\\QueryFilter\\PublishedQueryFilter', ];
- 当您直接创建 Query Filter 时,您可以将 Filterable 类作为参数传递以自动插入到
$filters
属性中。
php artisan make:query-filter PublishedQueryFilter --filterable=PostsFilterable
现在您的 PostsFilterable
类应该包含以下内容
<?php namespace App\Filters\Filterable; use TheJano\LaravelFilterable\Abstracts\FilterableAbstract; use TheJano\LaravelFilterable\Interfaces\FilterableInterface; class PostsFilterable extends FilterableAbstract implements FilterableInterface { /** * It contains list of Query Filters * * @var Array */ public array $filters = [ 'published' => 'App\\Filters\\QueryFilter\\PublishedQueryFilter', ]; }
最后一步是启用 PostsFilterable
到您的模型。
有三种方法可以启用它
-
什么都不做 :) 这将启用所有默认 Query Filters 到您的模型。
-
将 Filterable 类传递到模型的
filterableClass()
方法。
<?php namespace App\Models; use App\Filters\Filterable\PostsFilterable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use TheJano\LaravelFilterable\Traits\HasFilterableTrait; class Post extends Model { use HasFactory; use HasFilterableTrait; /** * Enable the filterable class to the model * * @return void */ public function filterableClass() { return PostsFilterable::class; } }
- 将作为参数传递到模型的
fliterable()
范围。该范围接受 3 个参数
public function scopeFilterable(Builder $builder, $request = null, $filterableClass = null, $filters = []): Builder
如果您将 Filterable 类作为第一个参数传递,底层软件包将为您处理它,并忽略 $request
变量,并使用 request()
助手函数。让我们看看下面的代码。
<?php namespace App\Http\Controllers; use App\Filters\Filterable\PostFilterable; use App\Models\Post; use Illuminate\Http\Request; class PostController extends Controller { public function index(Request $request) { $posts = Post::filterable(PostFilterable::class)->get(); return view('posts', compact('posts')); } }
您还可以通过 $filters
参数传递一些额外的 Query Filters,例如
<?php namespace App\Http\Controllers; use App\Filters\Filterable\PostFilterable; use App\Filters\QueryFilter\TitleQueryFilter; use App\Models\Post; use Illuminate\Http\Request; class PostController extends Controller { public function index(Request $request) { $posts = Post::filterable(PostFilterable::class,[ 'title' => TitleQueryFilter::class ])->get(); return view('posts', compact('posts')); } }
您不仅可以传递 Request
,还可以传递参数数组进行过滤。
默认 Query Filters
最后但同样重要的是,默认情况下,该包为每个可过滤类提供一些查询过滤器。配置文件包含可用的查询过滤器,包括:
date
查询过滤器,它返回两个日期之间的记录(从和到)。默认情况下,它使用created_at
字段。
/posts?date[from]=2022-06-01&date[to]=2022-07-01
或者,您可以传递一个自定义字段。分隔符是 BY
/posts?date[fromBYupdated_at]=2022-06-01&date[toBYupdated_at]=2022-07-01
order
查询过滤器,它按 ASC 或 DESC 对记录进行排序。默认情况下,它使用created_at
字段。
/posts?order=asc
或者,您可以传递一个自定义字段。
/posts?order[id]=asc
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献指南。
安全漏洞
请查看我们关于如何报告安全漏洞的安全策略。
鸣谢
许可
MIT 许可证(MIT)。有关更多信息,请参阅许可文件。