morfin / querystring-for-laravel
从 mehradsadeghi 分支而来。轻松根据 URL 查询字符串参数过滤查询。
Requires
- php: >=7.1
- laravel/framework: >=6.20.26
Requires (Dev)
- orchestra/testbench: ^4.0
This package is not auto-updated.
Last update: 2024-09-25 18:22:21 UTC
README
轻松根据 URL 查询字符串参数过滤查询。
兼容 Laravel 5.x 6.x 7.x 8.x.
目录
描述问题
你可能遇到过需要根据 URL 查询字符串中的给定参数过滤查询的情况。在开发完逻辑后,你可能会有这样的代码
$users = User::latest(); if(request('username')) { $users->where('username', request('username')); } if(request('age')) { $users->where('age', '>', request('age')); } if(request('email')) { $users->where('email', request('email')); } return $users->get();
这可以工作,但这不是一种好的做法。
当参数数量开始增加时,这种 if
语句的数量也会增加,你的代码会变得庞大且难以维护。
这也违反了 SOLID 原则中的开放/关闭原则,因为当你有新的参数时,你需要进入现有的代码并添加新的逻辑(这可能会破坏现有的实现)。
因此,我们必须设计一种方法来使我们的过滤器逻辑相互分离,并将它们应用于最终的查询,这正是这个包背后的整个想法。
用法
- 首先,你需要安装这个包
$ composer require mehradsadeghi/laravel-filter-querystring
use Mehradsadeghi\FilterQueryString\FilterQueryString; class User extends Model { use FilterQueryString; protected $filters = []; ... }
- 你需要在你的 Eloquent 查询中使用
filter()
方法。例如
User::select('name')->filter()->get();
可用方法
为了解释每个方法,假设我们在 users
表中有以下数据
假设我们的查询是这样的
User::filter()->get();
排序
排序相当于 SQL 语句中的 order by
,可以在 FilterQueryString
中灵活使用
约定
?sort=field
?sort=field,sort_type
?sort[0]=field1&sort[1]=field2
?sort[0]=field1&sort[1]=field2,sort_type
?sort[0]=field1,sort_type&sort[1]=field2,sort_type
在 User.php 中
protected $filters = ['sort'];
单个 sort
:
https://example.com?sort=created_at
输出
- 注意:当没有定义
sort_type
时,默认为asc
。
多个 sort
:
https://example.com?sort[0]=age,desc&sort[1]=created_at,desc
输出
请注意:无效值的 sort
参数将被忽略并不会有任何影响。
比较
比较由 6 个过滤器组成
- greater
- greater_or_equal
- less
- less_or_equal
- between
- not_between
约定
?greater=field,value
?greater_or_equal=field,value
?less=field,value
?less_or_equal=field,value
?between=field,value1,value2
?not_between=field,value1,value2
在 User.php 中
protected $filters = [ 'greater', 'greater_or_equal', 'less', 'less_or_equal', 'between', 'not_between' ];
例如,greater
的示例:
https://example.com?greater=age,20
输出
例如,not_between
的示例:
https://example.com?not_between=age,21,30
输出
请注意:无效值的比较参数将被忽略并不会有任何影响。
在
IN 子句相当于 SQL 语句中的 where in
。
约定
?in=field,value1,value2
在 User.php 中
protected $filters = ['in'];
示例:
https://example.com?in=name,mehrad,reza
输出
请注意:无效值的 in
参数将被忽略并不会有任何影响。
如
LIKE 子句相当于 SQL 语句中的 like '%value%'
。
约定
?like=field,value
?like[0]=field1,value1&like[1]=field2,value2
在 User.php 中
protected $filters = ['like'];
单个 like
:
https://example.com?like=name,meh
输出
多个 like
:
https://example.com?like[0]=name,meh&like[1]=username,dar
输出
请注意,如果like
参数的值无效,则将从查询中忽略它,并且不会对结果产生影响。
Where子句(默认过滤器)
通常,当您的查询字符串参数不是之前可用方法之一时,它将通过默认过滤器进行过滤,该默认过滤器是where
SQL语句。当您需要直接过滤您表中的一列时,这是一个合适的过滤器。
约定
?field=value
?field1=value&field2=value
?field1[0]=value1&field1[1]=value2
?field1[0]=value1&field1[1]=value2&field2[0]=value1&field2[1]=value2
假设我们想要过滤数据库列name
、username
和age
,在User.php中
protected $filters = ['name', 'username', 'age'];
示例:
https://example.com?name=mehrad
输出
示例:
https://example.com?age=22&username=dariush123
输出
示例:
https://example.com?name[0]=mehrad&name[1]=dariush
输出
示例:
https://example.com?name[0]=mehrad&name[1]=dariush&username[0]=mehrad123&username[1]=reza1234
输出
请注意,如果default
过滤器参数的值无效,则将从查询中忽略它,并且不会对结果产生影响。
自定义过滤器
通过自定义过滤器,您可以定义自己的方法作为过滤器。这有助于实现SOLID原则中的开放/封闭原则,因此每次需要新的过滤器时,您不必编辑以前的过滤器,而只需为它编写一个单独的方法。
让我们创建一个自定义过滤器。假设您想创建一个名为all_except
的过滤器,该过滤器检索除指定用户之外的所有用户
在 User.php 中
protected $filters = ['all_except']; public function all_except($query, $value) { return $query->where('name', '!=', $value); }
为了测试我们新添加的过滤器
https://example.com?all_except=mehrad
输出
注意,您自定义定义的过滤器具有最高优先级,这意味着您可以覆盖现有过滤器。
例如,让我们将in
过滤器修改为只接受3个值
在 User.php 中
protected $filters = ['in']; public function in($query, $value) { $exploded = explode(',', $value); if(count($exploded) != 4) { // throwing an exception or whatever you like to do } $field = array_shift($exploded); return $query->whereIn($field, $exploded); }
另一个自定义过滤器的良好示例是当您不想暴露数据库表的列名时。例如,假设我们不希望暴露在users
表中有一个名为username
的列
在 User.php 中
protected $filters = ['by']; public function by($query, $value) { return $query->where('username', $value); }
https://example.com?by=dariush123
输出
小贴士
为了防止您的模型变得混乱或被过滤器方法填充,您可以为此创建一个特质,并将有关过滤器的一切放入特质中。
条件过滤器
您的模型中的$filters
属性对该模型的作用类似于全局属性。这意味着当您在eloquent查询上使用filter()
方法时,它将始终执行所有$filters
过滤器。
可能会出现这样的情况,基于条件您需要指定确切的过滤器,您希望对其进行过滤。
为了实现这一点,您可以在filter()
方法中指定所需的过滤器作为参数。
示例
在您的查询中
User::filter('in')->get();
in=name,mehrad,reza&like=name,mehrad
输出
如果未指定in
参数,查询的结果将只有一条记录(mehrad
)。
另一个示例
在您的查询中
User::filter('like', 'name')->get();
like=name,mehrad,reza,dariush,hossein&name[0]=mehrad&name[1]=hossein&username=mehrad
输出
您的支持很重要
如果您觉得这个包很有用,并希望鼓励我维护和改进它,只需按下星号按钮即可表达您的意愿。
用一杯茶奖励我 🍵
请按照您所在国家的茶杯价值给我发来相应的金额,这样我就会有精力维护这个包。
- Ethereum: 0x2D5BFdEc132F9F0E9498Fb0B58C800db4007D154