mhomayoun / laravel7-filterable
使用URL查询字符串来过滤Eloquent查询。
Requires
- php: >=7.3
- illuminate/database: 7.*
- illuminate/http: 7.*
- illuminate/support: 7.*
Requires (Dev)
- laravel/framework: 7.*
- limedeck/phpunit-detailed-printer: ^5.0
- orchestra/testbench: 5.*
- phpunit/phpunit: 8.*
README
此包允许您通过查询字符串轻松处理数据库过滤。该思路来自Jeffrey的视频(付费墙后)之一。一个简单的例子可能如下所示:/users?filter-username=~joe
将导致SQL查询select * from users where "username" like '%joe%'
。
安装
您可以通过composer安装此包
composer require mhomayoun/laravel7-filterable
Laravel将自动发现此包。如果您觉得过时,请禁用自动发现,并将Kyslik\LaravelFilterable\FilterableServiceProvider::class
添加到您的config/app.php
文件中的提供者数组中。
您可以通过以下 artisan 命令发布配置文件: php artisan vendor:publish
。
简介
该包允许您创建并应用两种类型的过滤器:自定义和通用。
自定义过滤器
自定义过滤器与Jeffrey的视频中的过滤器类似。您在构建器实例上定义逻辑,然后通过本地作用域应用它。
假设一个产品需要显示最近创建的记录。您在过滤器类中创建一个方法recent($minutes = null)
,它返回构建器实例
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)); }
注意:完整示例将在后面展示
通用过滤器
通用过滤器是在配置文件中定义的。默认情况下,该包支持过滤timestamps
、ranges
、ins
、booleans
和strings
。
/?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
通用过滤器的默认运算符矩阵
使用方法
在同时使用自定义或通用过滤器时,您必须
- 在具有签名
scopeFilter(Builder $query, FILTERNAME $filters)
的模型上具有local scope
- 具有特定的(
FILTERNAME
)过滤器类,该类扩展了以下之一Kyslik\LaravelFilterable\Generic\Filter
类 - 允许使用自定义和通用过滤器Kyslik\LaravelFilterable\Filter
类 - 仅允许使用自定义过滤器
- 在控制器中调用作用域
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?recent
或 users?recently
或 users?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']; }
接下来,您需要通过 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(); }
现在您已经准备好对 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)。请参阅 许可文件 以获取更多信息。