coliving / eloquent-filter
Eloquent Filter 是一个通过查询字符串过滤模型数据的包。易于使用且完全动态。
Requires
- php: ^7.3|^8.0|^8.1
- illuminate/container: 5.8.*|~6.0|~7.0|~8.0|~9.0
- illuminate/database: 5.8.*|~6.20.14|~7.0|~8.0|~9.0
- illuminate/pagination: 5.8.*|~6.0|~7.0|~8.0|~9.0
- illuminate/support: 5.8.*|~6.0|~7.0|~8.0|~9.0
Requires (Dev)
- fzaninotto/faker: ^1.9|1.9.x-dev
- illuminate/macroable: ^8.0|^9.0
- laravel/legacy-factories: 1.0.2|1.0.3|1.0.4|1.0.5|1.1.0
- mockery/mockery: 1.3.*|1.3.*|1.3.*|1.4.x-dev|1.4.x-dev|1.4.2
- orchestra/database: v3.7.0|v3.8.0|v4.0.0|v5.0.0|v6.x-dev
- orchestra/testbench: 3.7.*|3.8.*|4.*|5.*|^6.0|^6.6.0
- phpunit/phpunit: 6.*|7.0.*|7.5|8.3|8.5|9.3
- dev-master
- 3.0.0
- 2.5.7
- 2.5.6
- 2.5.4
- 2.5.3
- 2.5.2
- 2.5.1
- 2.5.0
- 2.4.8
- 2.4.6
- 2.4.5
- 2.4.4
- 2.4.3
- 2.4.2
- 2.4.1
- 2.4.0
- 2.3.9
- 2.3.8
- 2.3.7
- 2.3.5
- 2.3.2
- 2.3.0
- 2.2.5
- 2.2.1
- 2.1.9
- 2.1.5
- 2.1.0
- 2.0.9
- 2.0.0
- 1.6.9
- 1.6.7.x-dev
- 1.6.7
- 1.6.5.x-dev
- 1.6.5
- 1.6.2
- 1.6.0.x-dev
- 1.6.0
- 1.5.8
- 1.5.7
- 1.5.6
- 1.5.5
- 1.5.3.x-dev
- 1.5.3
- 1.5.2.x-dev
- 1.5.2
- 1.5.1.x-dev
- 1.5.1
- 1.5.0.x-dev
- 1.5.0
- 1.4.3
- 1.4.2
- 1.4.1.x-dev
- 1.4.1
- 1.4.0
- 1.3.2
- 1.3.0
- 1.1.9
- 1.1.8
- 1.1.7
- 1.1.6
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- dev-support_laravel_9
- dev-revert-187-master
- dev-laravel-9
- dev-v-2.4
- dev-analysis-BMaQOr
- dev-analysis-jLboA2
- dev-analysis-d0bvPj
- dev-analysis-nNwZ00
- dev-analysis-QMJD3Z
- dev-analysis-5ZnoAj
- dev-analysis-yvBJrG
- dev-analysis-QMy14w
- dev-analysis-64Y11P
- dev-analysis-64YDd6
- dev-analysis-aj1pyZ
- dev-analysis-m4RDBV
- dev-analysis-0gxgnW
- dev-analysis-m43AaV
- dev-analysis-VrkmpB
- dev-analysis-L3kKOn
- dev-analysis-9m1295
- dev-analysis-YjdPkY
- dev-analysis-64lRQo
- dev-analysis-nNG5jv
- dev-analysis-4xQVwN
- dev-analysis-ajG51o
- dev-analysis-bQ2D2w
- dev-analysis-64lm9M
- dev-v-2.3
- dev-analysis-e7kOa7
- dev-analysis-m46eME
- dev-analysis-4x61je
- dev-analysis-0gDjvw
- dev-analysis-rdMpE3
- dev-analysis-WN3pxN
- dev-analysis-ZlBKpg
- dev-analysis-M1Nr52
- dev-analysis-jLMBrZ
- dev-analysis-ajE5l7
- dev-analysis-wj5Qk9
- dev-analysis-BMQP9L
- dev-analysis-L3xWAk
- dev-analysis-kayoD4
- dev-analysis-Yj0wJy
- dev-v-2
- dev-analysis-ZlrB6Y
- dev-analysis-BMxxr7
- dev-analysis-0gKymM
- dev-analysis-7aQA56
- dev-analysis-4xRmon
- dev-analysis-646w2W
- dev-analysis-7aQW56
- dev-analysis-d0WMNJ
- dev-analysis-jLWBbZ
- dev-analysis-J2J97v
- dev-analysis-YjQ2eo
- dev-analysis-L3ol5n
- dev-analysis-YjMw9A
- dev-analysis-gOeoB1
- dev-analysis-0gAA5j
- dev-analysis-9mynDa
- dev-analysis-e7j7D2
- dev-analysis-2QvelB
- dev-analysis-wj0xnK
- dev-analysis-yvExnj
- dev-analysis-2Qv9gZ
- dev-analysis-rdEoOD
- dev-analysis-gO1Vnk
- dev-analysis-NApk94
- dev-analysis-WNl60e
- dev-analysis-4x7l6n
- dev-analysis-BMyb0W
- dev-mock-test-relation
- dev-analysis-VrY9l3
- dev-analysis-NADlve
- dev-mock-test
- dev-analysis-nNLR6g
- dev-analysis-5ZPy9x
- dev-analysis-3wWojA
- dev-mehdi-fathi-patch-1
- dev-mehdi-travic-ci
- dev-analysis-Px5ZNP
- dev-analysis-Vrjnl6
- dev-mehdi-dev
- dev-analysis-ajVmmB
- dev-analysis-KZoo76
- dev-mehdi-fathi-working-4
- dev-analysis-q1Vobv
- dev-analysis-8AZ3Dl
- dev-analysis-qyyvdN
- dev-analysis-8A0Vw9
- dev-analysis-Xk1bxJ
- dev-analysis-zYGJR9
- dev-analysis-8bw3e2
- dev-analysis-XaPGJo
- dev-analysis-8mQ51V
- dev-analysis-zerKYP
- dev-analysis-86WAgl
- dev-analysis-z922wP
- dev-analysis-8LWdA6
- dev-analysis-qMmmnl
- dev-analysis-qvAA4x
- dev-mehdi-fathi-working-2
- dev-analysis-zRB9wp
- dev-analysis-XZV7JD
- dev-analysis-XkGPe1
- dev-analysis-zOwneB
- dev-analysis-XWOeZP
- dev-mehdi-fathi-working
- dev-analysis-XZV7eg
- dev-analysis-zEZawD
- dev-revert-2-master
- dev-add-stickler-config
This package is not auto-updated.
Last update: 2024-09-18 20:55:00 UTC
README
Eloquent Filter 为 Laravel 的 Eloquent 模型添加自定义过滤器。易于使用且完全动态。
目录
要求
- PHP 7.2+, 8.0, 8.1 (新版本)
- Laravel 5.8+,6.x,7.x,8.x,9.x(推荐稳定版)
🎤 介绍
假设我们想要制作一个带有多个过滤选项参数的高级搜索页面。
没有 Eloquent Filter 的简单实现
请求 URI 可能看起来像这样
https://:8000/users/index?age_more_than=25&gender=male&created_at=25-09-2019
在控制器中的简单实现可能如下所示
<?php namespace App\Http\Controllers; use App\User; use Illuminate\Http\Request; class UserController extends Controller { public function index(Request $request) { $users = User::where('is_active', true); if ($request->has('age_more_than')) { $users->where('age', '>', $request->age_more_than); } if ($request->has('gender')) { $users->where('gender', $request->gender); } if ($request->has('created_at')) { $users->where('created_at','>=', $request->created_at); } return $users->get(); } }
这个解决方案很简单,但效果不错。但你需要为每个需要的过滤器添加一个条件。特别是对于更复杂的过滤,你的代码可能会迅速变成一个怪物!💥
使用 Eloquent Filter 的简单实现
Eloquent Filter 可以帮助你解决这个问题。只需设置查询字符串来与它一起工作。这将节省你的时间并最小化你的代码复杂度。
安装 Eloquent Filter 后的请求 URI 可能如下所示
https://:8000/users/list?age_more_than[operator]=>&age[value]=35&gender=male&created_at[operator]==>&created_at[value]=25-09-2019
在控制器中,你只需要这一行
/** * Class UsersController. */ namespace App\Http\Controllers; use App\User; class UsersController { public function list() { return User::filter()->get(); } }
使用这个 Eloquent filter 实现,你可以使用所有文档中记录的过滤器!
🔌 安装
1- 运行以下 Composer 命令以安装最新版本
$ composer require coliving/eloquent-filter
-
注意 对于低于 5.8 的 Laravel 版本,应安装 2.2.5 版本
$ composer require mehdi-fathi/eloquent-filter:2.2.5
2- 将 eloquentFilter\ServiceProvider::class
添加到 app.php 中的提供者
'providers' => [ /* * Package Service Providers... */ eloquentFilter\ServiceProvider::class ],
3- 将 Facade 'EloquentFilter' => eloquentFilter\Facade\EloquentFilter::class
添加到 app.php 中的别名
'alias' => [ /* * Facade alias... */ 'EloquentFilter' => eloquentFilter\Facade\EloquentFilter::class, ],
就是这样!享受吧!💥
📖 基本用法
配置模型并设置白名单
将 Filterable 特性添加到你的模型中,并在白名单数组中设置你想要过滤的字段。你也可以在你的模型中覆盖此方法。
use eloquentFilter\QueryFilter\ModelFilters\Filterable; class User extends Model { use Filterable; private static $whiteListFilter =[ 'id', 'username', 'email', 'created_at', 'updated_at', ]; }
你可以为该过滤器设置 *
字符,如以下示例所示
private static $whiteListFilter = ['*'];
你可以在方法中动态添加或设置 $whiteListFilter
。例如
将数组设置为 WhiteListFilter
- 注意 此方法会覆盖
$whiteListFilter
数组
User::setWhiteListFilter(['name']);
向 WhiteListFilter 添加新字段
User::addWhiteListFilter('name');
在控制器中使用
按照以下示例更改 Laravel 项目的控制器代码
namespace App\Http\Controllers; /** * Class UsersController. */ class UsersController { public function list() { if (!empty(request()->get('username'))) { $users = User::ignoreRequest('perpage')->filter()->with('posts') ->orderByDesc('id')->paginate(request()->get('perpage'),['*'],'page'); } else { $users = User::filter( ['username' => ['mehdi','ali']] )->with('posts')->orderByDesc('id')->paginate(10,['*'],'page'); } } }
注意 Eloquent Filter 默认使用查询字符串在 Laravel 中进行查询。虽然如此,你可以将数组设置为模型的 filter
方法,以创建自己的自定义条件,而不使用查询字符串。
注意 因此,你必须自行取消 perpage 参数。你只能设置页面参数以分页此参数,该参数会从过滤器中忽略。
- 你可以使用以下代码忽略一些请求参数。
User::ignoreRequest(['perpage']) ->filter() ->paginate(request()->get('perpage'), ['*'], 'page');
调用 ignoreRequest
来忽略一些你不想在 eloquent 过滤器条件中使用的要求。例如,每页参数永远不会在 eloquent 过滤器条件中。这与分页方法相关。在 Laravel 的 Eloquent 过滤器中,默认忽略 page
参数。
- 你可以过滤一些请求参数来在 Eloquent 过滤器中使用。
User::AcceptRequest(['username','id']) ->filter() ->paginate(request()->get('perpage'), ['*'], 'page');
调用 AcceptRequest
将接受你想要在 Eloquent 过滤器条件中使用的要求。例如,username
和 id
参数将在 eloquent 过滤器条件中。请注意,你必须在模型中设置 $whiteListFilter
。此方法对于用户通过查询字符串进行查询字符串操作非常有用。
- 另一个 eloquent 过滤器过滤器的示例用途。
User::filter()->paginate();
-
EloquentFilter::filterRequests()
获取所有 Eloquent 过滤器使用的参数。你可以设置键来获取特定索引。例如,EloquentFilter::filterRequests('username')
获取用户名索引。 -
EloquentFilter::getAcceptedRequest()
获取由 AcceptRequest 方法设置的参数。 -
EloquentFilter::getIgnoredRequest()
获取由 getIgnoreRequest 方法设置的忽略参数。
简单示例
你只需在控制器方法中传递数据 blade 表单到查询字符串或生成查询字符串。例如
简单 Where
/users/list?email=mehdifathi.developer@gmail.com
SELECT ... WHERE ... email = 'mehdifathi.developer@gmail.com'
/users/list?first_name=mehdi&last_name=fathi
SELECT ... WHERE ... first_name = 'mehdi' AND last_name = 'fathi'
Where In
此示例创建方法 whereIn
。
/users/list?username[]=ali&username[]=ali22&family=ahmadi
SELECT ... WHERE ... username in ('ali','ali22') AND family = 'ahmadi'
OrWhere (新功能 🔥)
此示例创建方法 orWhere
。
/users/list?name=mehdi&username=fathi&or[username]=ali
SELECT ... WHERE ... name = 'mehdi' AND username = 'fathi' or username = 'ali'
Where like
如果你打算根据 like 条件进行查询,你可以通过此示例进行。
/users/list?first_name[like]=%John%
SELECT ... WHERE ... first_name LIKE '%John%'
Where 通过操作符
你可以在查询字符串中设置任何 MySQL 操作符。
/users/list?count_posts[operator]=>&count_posts[value]=35
SELECT ... WHERE ... count_posts > 35
/users/list?username[operator]=!=&username[value]=ali
SELECT ... WHERE ... username != 'ali'
/users/list?count_posts[operator]=<&count_posts[value]=25
SELECT ... WHERE ... count_posts < 25
Where 嵌套关系模型 (新功能 🔥)
你只需通过查询字符串的数组即可设置所有嵌套关系。例如,用户模型与帖子相关联。帖子表与订单表相关联。你可以在查询字符串中设置 'posts[count_post]' 和 'posts[orders][name]' 来创建查询条件。请注意,你必须在 User 模型中设置 'posts.count_post' 和 'posts.orders.name'。
use eloquentFilter\QueryFilter\ModelFilters\Filterable; class User extends Model { use Filterable; private static $whiteListFilter =[ 'username', 'posts.count_post', 'posts.category', 'posts.orders.name', ]; /** * @return \Illuminate\Database\Eloquent\Relations\belongsTo */ public function posts() { return $this->belongsTo('Models\Post'); } }
/users/list?posts[count_post]=876&username=mehdi
select * from "users" where exists
(select * from "posts" where "posts"."user_id" = "users"."id"
and "posts"."count_post" = 876)
and "username" = "mehdi"
- 上述示例与不使用 eloquent 过滤器的相同代码。请在代码部分下检查。
$user = new User(); $builder = $user->with('posts'); $builder->whereHas('posts', function ($q) { $q->where('count_post', 876); })->where('username','mehdi');
Where 数组的嵌套关系模型
你可以传递数组来创建 whereIn 条件。
/users/list?posts[category][]=php&posts[category][]=laravel&posts[category][]=jquery&username=mehdi
select * from "users" where exists
(select * from "posts" where
"posts"."category" in ('php','laravel','jquery') )
and "username" = "mehdi"
特殊参数
你可以在查询字符串中设置特殊参数 limit
和 orderBy
来通过它们进行查询。
/users/list?f_params[limit]=1
SELECT ... WHERE ... order by `id` desc limit 1 offset 0
/users/list?f_params[orderBy][field]=id&f_params[orderBy][type]=ASC
SELECT ... WHERE ... order by `id` asc
/users/list?f_params[orderBy][field]=id,count_posts&f_params[orderBy][type]=ASC
SELECT ... WHERE ... order by `id` asc, `count_posts` asc
Where between
如果你打算基于日期进行查询,你必须填写查询字符串中的键 start
和 end
。因此,你可以将其设置为查询字符串。这些参数用于日期筛选。
/users/list?created_at[start]=2016/05/01&created_at[end]=2017/10/01
SELECT ... WHERE ... created_at BETWEEN '2016/05/01' AND '2017/10/01'
高级 Where
/users/list?count_posts[operator]=>&count_posts[value]=10&username[]=ali&username[]=mehdi&family=ahmadi&created_at[start]=2016/05/01&created_at[end]=2020/10/01
&f_params[orderBy][field]=id&f_params[orderBy][type]=ASC
select * from `users` where `count_posts` > 10 and `username` in ('ali', 'mehdi') and
`family` = ahmadi and `created_at` between '2016/05/01' and '2020/10/01' order by 'id' asc limit 10 offset 0
因此,查询字符串的字段与模型中的 $whiteListFilter
中的数据库行表相同,或在你的模型中声明方法作为覆盖方法。覆盖方法可以被视为自定义查询筛选器。
自定义查询过滤器
Eloquent Filter 默认不支持所有条件。在这种情况下,你可以创建一个覆盖方法。如果你打算自己创建查询筛选器,你可以轻松做到这一点。
你应该运行命令来创建特质并在模型中使用它
php artisan eloquentFilter:filter users
namespace App\ModelFilters; use Illuminate\Database\Eloquent\Builder; /** * Trait UsersFilter. */ trait UsersFilter { /** * This is a sample custom query * @param \Illuminate\Database\Eloquent\Builder $builder * @param $value * * @return \Illuminate\Database\Eloquent\Builder */ public function sample_like(Builder $builder, $value) { return $builder->where('username', 'like', '%'.$value.'%'); } }
-注意 这些查询字符串的字段与特质中的方法相同。在你的模型中使用特质
/users/list?sample_like=a
select * from `users` where `username` like %a% order by `id` desc limit 10 offset 0
use App\ModelFilters\UsersFilter; class User extends Model { use UsersFilter,Filterable; protected $table = 'users'; protected $guarded = []; private static $whiteListFilter =[ 'id', 'username', 'email', 'created_at', 'updated_at', ]; }
自定义检测条件
有时你想要创建自定义条件来创建 Eloquent Filter 默认不支持的新查询。好消息是,你现在可以从 eloquent 过滤器中创建自定义条件。
你可以创建条件来在检查之后生成新查询。(新功能 🔥 )。例如
我们必须有两个类。第一个检测条件,第二个类生成查询。
- 步骤 1:创建一个类来检测某些条件
use eloquentFilter\QueryFilter\Detection\DetectorContract; /** * Class WhereRelationLikeCondition. */ class WhereRelationLikeCondition implements DetectorContract { /** * @param $field * @param $params * @param $is_override_method * * @return string|null */ public static function detect($field, $params, $is_override_method = false): ?string { if (!empty($params['value']) && !empty($params['limit']) && !empty($params['email'])) { $method = WhereRelationLikeConditionQuery::class; } return $method ?? null; } }
- 步骤 2:之后,创建一个类来生成查询。在此示例中,我们创建
WhereRelationLikeConditionQuery
类
use eloquentFilter\QueryFilter\Queries\BaseClause; use Illuminate\Database\Eloquent\Builder; /** * Class WhereRelationLikeConditionQuery. */ class WhereRelationLikeConditionQuery extends BaseClause { /** * @param $query * * @return Builder */ public function apply($query): Builder { return $query ->whereHas('posts', function ($q) { $q->where('comment', 'like', "%" . $this->values['like_relation_value'] . "%"); }) ->where("$this->filter", '<>', $this->values['value']) ->where('email', 'like', "%" . $this->values['email'] . "%") ->limit($this->values['limit']); } }
- 步骤 3:你创建方法
EloquentFilterCustomDetection
来在模型中返回条件的检测数组。
use eloquentFilter\QueryFilter\ModelFilters\Filterable; class User extends Model { use Filterable; private static $whiteListFilter =[ 'username', 'posts.count_post', 'posts.category', 'posts.orders.name', ]; /** * @return \Illuminate\Database\Eloquent\Relations\belongsTo */ public function posts() { return $this->belongsTo('Models\Post'); } public function EloquentFilterCustomDetection(): array { return [ WhereRelationLikeCondition::class ]; } }
- 查询参数中的每一个都在默认的eloquent过滤器检测之后,首次用于检测
WhereRelationLikeCondition
。
在上面的例子中,创建一个方法EloquentFilterCustomDetection
并返回条件数组类。
/users/list?username[value]=mehdi&username[limit]=10&username[email]=mehdifathi&username[like_relation_value]=mehdi&count_posts=10
select * from "users"
where exists (select * from "posts" where
"users"."post_id" = "posts"."id"
and "comment" like ?) and "username" <> ? and "email" like ? and "count_posts" = ? limit 10
只需运行代码User::filter();
即可查看结果。
-注意您还可以通过使用方法SetCustomDetection
即时设置自定义检测。例如
$users = User::SetCustomDetection([WhereRelationLikeCondition::class])->filter();
-注意您可以通过以下代码即时禁用EloquentFilterCustomDetection
User::SetLoadDefaultDetection(false)->filter();
-注意您可以设置多个检测条件。例如
class User extends Model { use Filterable; public function EloquentFilterCustomDetection(): array { return [ WhereRelationLikeCondition::class, WhereRelationLikeVersion2Condition::class, WhereRelationLikeVersion3Condition::class, ]; } }
EloquentFilter::getInjectedDetections()
获取您所有自定义注入的检测。
-注意每个自定义检测都会在默认eloquent过滤器检测之前运行。
配置
您可以为Eloquent Filter生成一个配置文件进行配置。
发布配置
php artisan vendor:publish --provider="eloquentFilter\ServiceProvider"
配置
-
您可以在配置文件(eloquentFilter.php)中禁用/启用Eloquent Filter。
'enabled' => env('EloquentFilter_ENABLED', true),
-
Eloquent Filter识别查询字符串中的每个参数。也许您有一个不想被Eloquent Filter识别的查询字符串。您可以使用
ignoreRequest
来达到这个目的。但我们有一个干净的解决方案。您可以在配置文件中设置request_filter_key
参数。因此,每个查询字符串都将通过request_filter_key
参数进行识别。'request_filter_key' => '', // filter
例如,如果您设置'request_filter_key' => 'filter',
那么Eloquent Filter将识别filter
查询字符串。
/users/list?filter[email]=mehdifathi.developer@gmail.com
-
您可以在配置文件(eloquentFilter.php)中禁用/启用Eloquent Filter的所有自定义检测。
'enabled_custom_detection' => env('EloquentFilter_Custom_Detection_ENABLED', true),
-
您应该在
ignore_request
中设置索引数组以忽略所有过滤器。'ignore_request' => [] //[ 'show_query','new_trend' ],
魔术方法
魔法方法是您可以在Eloquent Filter中用作包装器的一组方法。例如,在过滤之前序列化数据或更改响应中的数据等。现在Eloquent Filter有serializeRequestFilter
、ResponseFilter
。
请求过滤器
Eloquent Filter有一个专门用于在Eloquent Filter处理之前更改注入请求的魔法方法。该方法称为SerializeRequestFilter。您只需在您的模型中实现SerializeRequestFilter
方法即可。例如
class User extends Model { use Filterable; public function serializeRequestFilter($request) { $request['username'] = trim($request['username']); return $request; } }
如上述代码所示,您可以在Eloquent Filter运行之前修改模型中的每个查询参数,在serializeRequestFilter
方法中。这是设置user_id或转换日期或删除空格等时的实用方法。
响应过滤器
响应过滤器是一个专门用于在Eloquent Filter处理后更改响应的魔法方法。该方法称为ResponseFilter
。您应该在您的模型中实现ResponseFilter
方法。例如
class User extends Model { use Filterable; public function ResponseFilter($response) { $data['data'] = $response; return $data; } }
- 如果您对Eloquent Filter有任何想法,我将很高兴听到。