奇技淫巧:利用Pipeline进行laravel查询简化
奇技淫巧:利用Pipeline进行laravel查询简化
本文编写时间:2024-06-15
原文:分享:屎山警告!Pipeline竟优雅的处理了Laravel多条件查询
原作者:抄X码科技有限公司
需求
1、想学习 Laravel 中的管道 Pipeline 用法。
2、同时想简化 Laravel 项目中的查询。
3、我测试的版本 laravel:10.48,
4、我对原文代码做了一丁点修改,更加实用一些。
5、为了学习代码,我写个控制器,一个trait,两个通用过滤器类,一个模型类,
6、想图省事都放 models 目录下。
代码
写个 trait 增强模型类,路径自由。
<?php
namespace App\Models;
use Illuminate\Pipeline\Pipeline;
// 对模型类增强,但是同样可以做成父类供子类调用,效果一样。
trait Filterable
{
// 基本方法,但可以不管他。
public function scopeFilter($query, array $through)
{
return app(Pipeline::class)
->send($query)
->through($through)
->thenReturn();
}
// 适用于 表字段和请求参数名相同,且查询等值的情况。
public function scopeStringFilter($query, array $through)
{
$newArr = [];
foreach ($through as $value) {
$newArr[] = '\App\Models\StringFilter:' . $value;
}
return app(Pipeline::class)
->send($query)
->through($newArr)
->thenReturn();
}
// 适用于 表字段和请求参数名相同,且查询like的情况。
public function scopeStringLikeFilter($query, array $through)
{
$newArr = [];
foreach ($through as $value) {
$newArr[] = '\App\Models\StringLikeFilter:' . $value;
}
return app(Pipeline::class)
->send($query)
->through($newArr)
->thenReturn();
}
}
写两个 通用过滤器。
<?php
namespace App\Models;
class StringFilter
{
public function handle($query, $next,$column)
{
if ( $v = request()->input( $column )) {
$query->where($column, $v);
}
return $next($query);
}
}
<?php
namespace App\Models;
class StringLikeFilter
{
public function handle($query, $next,$column)
{
if ( $v = request()->input( $column )) {
$query->where($column, 'like', '%'. $v. '%');
}
return $next($query);
}
}
我的模型类。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
use Filterable;
protected $table = 'order';
protected $primaryKey = 'id';
public $timestamps = false;
protected $guarded = [];
}
我的控制器
这个意思就是 请求中如果有 type和 category的参数
就 where type=请求type and category= 请求category
如果请求中有 name 参数。
就 where name like ‘%name%’
class TestController extends Controller
{
public function index(Request $request)
{
return Order::query()->stringFilter([
'type',
'category',
])->stringLikeFilter([
'name',
])->get();
// 等价写法。
//if ($request->input('type')){
// $query->where('type', $request->input('type'));
//}
//if ($request->input('category')){
// $query->where('category', $request->input('category'));
//}
//if ($request->input('name')){
// $query->where('name','like', '%'.$request->input('name').'%');
//}
}
}
总结
1、代码简化了,爽歪歪
2、突出一个可玩性
本作品采用《CC 协议》,转载必须注明作者和本文链接
你是否在寻找:github.com/Tucker-Eric/EloquentFil...
可以看一下when() 方法
玩玩可以, 在实际的复杂业务中既增加了代码量还应对不了需求的变化,后期维护也很麻烦
还是没经历过一天逻辑改十次的毒打,经历过后就老实了 :grinning:
现在写的项目,真的怕这种..非常不利于后期维护..
如果项目是分层结构,例如controller/service/repository等,request不应该侵入到controller之后的分层,只传递业务数据值或业务数据对象给下层即可,随着业务迭代,查询复杂度会增加,简单业务这么写没啥问题,复杂业务不建议。