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”适配

让PHP再次伟大
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 13

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

1年前 评论
勇敢的心 (楼主) 1年前
勇敢的心 (楼主) 1年前
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 ;
}
}

这样是不是可以

1年前 评论
勇敢的心 (楼主) 1年前
luyang (作者) 1年前

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

1年前 评论
勇敢的心 (楼主) 1年前

你可能缺少一个枚举类

1年前 评论

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

1年前 评论

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