奇技淫巧:利用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 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 8
1周前 评论
yyy123456 (楼主) 1周前
Imuyu (作者) 1周前

玩玩可以, 在实际的复杂业务中既增加了代码量还应对不了需求的变化,后期维护也很麻烦

1周前 评论

还是没经历过一天逻辑改十次的毒打,经历过后就老实了 :grinning:

1周前 评论

现在写的项目,真的怕这种..非常不利于后期维护..

1周前 评论

如果项目是分层结构,例如controller/service/repository等,request不应该侵入到controller之后的分层,只传递业务数据值或业务数据对象给下层即可,随着业务迭代,查询复杂度会增加,简单业务这么写没啥问题,复杂业务不建议。

1周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
55
粉丝
10
喜欢
62
收藏
100
排名:531
访问:1.5 万
私信
所有博文
社区赞助商