SQL和代码条件判断如何相互转换?

场景

在“获取用户订单列表”接口中,只有可能查询“已支付”的订单,也有可能返回某个订单“是否可以退款”的参数

常规代码

class Order extends Model
{
    //作用域:已支付
    public function scopePay($query)
    {  
        return $query->where('is_pay', 1);
    }

    //访问器:是否允许发货(等于1时,后台展示发货按钮)
    public function getIsAllowSendAttribute($value, $data)
    {
        //是否已支付(可能还有其他条件,暂且不议)
        if ($data['is_pay'] == 1) {
            return 1;
        }

        return 0;
    }
}

问题

这里这么写就有问题,当我需要用增加判断条件的时候就要两个地方都要改,有没有比较好的方式能把代码的逻辑判断和SQL转换,或者说有没有composer包来干这件事

其实也能自己写,但是and\or\in,太麻烦,而且容易出BUG

简单案例,我大体描述一下我的意思,不要吹毛求疵,这只是简单的“=”转换,还有“<>”、“in”、“not in”等等,还有and\or这些就很复杂了,自己写实在不现实,所以,想问问有没有比较成熟的代码条件和SQL转换的包

class Order extends Model
{
    //待支付表达式,以后有条件修改,我只需要改表达式,其他查询条件或者访问器都不需要改动,就是新人来了也可以轻松维护
    public $pay_ex = [
        ['is_pay', '=', 1],
    ];

    //获取表达式
    private function getPayEx(type = 'bool', $data = []) {
        $sql = [];
        foreach ($this->pay_ex as $ex) {
            switch ($data[$ex[1]]) {
                case '=':
                    switch ($type) {
                        case 'bool':
                            if ($data[$ex[0]] != $ex[2]) {
                                return false;
                            }
                        case 'sql':
                            $sql[] = [$ex[0], $ex[2]];
                    }
                    break;
                case '<>':
                    # 不等于判断
                    break;
                case 'in':
                    # 介于列表判断
                    break;
            }
        }

        switch ($type) {
            case 'bool':
                return true;
            case 'sql':
                return $sql
        }
    }

    //作用域:已支付
    public function scopePay($query)
    {  
        return $query->where($this->getPayEx($this->pay_ex, 'sql'));
    }

    //访问器:是否允许发货(等于1时,后台展示发货按钮)
    public function getIsAllowSendAttribute($value, $data)
    {
        //是否已支付(可能还有其他条件,暂且不议)
        if ($this->getPayEx($this->pay_ex, 'bool', $data)) {
            return 1;
        }

        return 0;
    }
}

如果真的没有这样的包,那我就自己写一个,先从“=”+“and”适配

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 13

你说有没有一种可能 不使用作用域呢

2周前 评论
勇敢的心 (楼主) 2周前
勇敢的心 (楼主) 2周前
class Order extends Model
{

const STATUS_PAID = 1;

//作用域:已支付
public function scopePay($query)
{  
    return $query->where('is_pay', self::STATUS_PAID );
}

//访问器:是否允许发货(等于1时,后台展示发货按钮)
public function getIsAllowSendAttribute($value, $data)
{
    //是否已支付(可能还有其他条件,暂且不议)
    if ($this->isPaid()) {
        return 1;
    }

    return 0;
}

public function isPaid()
{
  return $this->attribute('is_pay') === self::STATUS_PAID ;
}
}

这样是不是可以

2周前 评论
勇敢的心 (楼主) 2周前
luyang (作者) 2周前

这样耦合太严重,是否可支付和检索条件没有必然关系,还是建议分开,检索是检索,动作是动作

2周前 评论
勇敢的心 (楼主) 2周前

你可能缺少一个枚举类

2周前 评论

如果我没理解错的话,个人感觉这样耦合性太强了,一个是对已经查出来的数据进行转换 (是否允许发货),一个是对未取出的sql语句进行条件拼接判断

2周前 评论

此处推荐下我写的 :joy: 自动化接口

2周前 评论
勇敢的心 (楼主) 2周前
wade (作者) 2周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!