个人感觉 Eloquent ORM 的 where 条件解析场景并不是那么的丰富,很多条件的拼装都需要引入额外的 orWhere, whereNotIn, whereBetween, whereNotBetween 来辅助完成。这样在做一些抽象的底层查询方法时,不是很友好,上层传递的查询条件是不确定的,如果能灵活的解析各种混合式的查询条件(用数组的方式描述),使用起来会更高效灵活些。

/**

  • 渲染复杂的 where 查询条件
  • @param Builder $query
  • @param $conditions
    */

public static function renderWhereMixedEloquent(Builder $query, $conditions)
{

$lastEl = end($conditions);
reset($conditions);
if (is_string($lastEl) && (('or' == $lastEl || 'and' == $lastEl))) {
    $logic = $lastEl;
    array_pop($conditions);
} else {
    $logic = 'and';
}
$conditionsKeys     = array_keys($conditions);
$conditionsKeyFirst = $conditionsKeys[0];

if (is_numeric($conditionsKeyFirst)) {
    if (is_array($conditions[$conditionsKeyFirst])) {
        if ('or' == $logic) {
            $query->where(function (Builder $query) use ($conditions) {
                foreach ($conditions as $conditionsSub) {
                    $query->orWhere(function (Builder $query) use ($conditionsSub) {
                        static::renderWhereMixedEloquent($query, $conditionsSub);
                    });
                }
            });
        } else {
            $query->where(function (Builder $query) use ($conditions) {
                foreach ($conditions as $conditionsSub) {
                    $query->where(function (Builder $query) use ($conditionsSub) {
                        static::renderWhereMixedEloquent($query, $conditionsSub);
                    });
                }
            });
        }
    } else {
        $operator = $conditions[1];
        switch ($operator) {
            case 'in':
                $query->whereIn($conditions[0], $conditions[2], $logic);
                break;
            case 'between':
                $query->whereBetween($conditions[0], $conditions[2], $logic);
                break;
            case 'not in':
                $query->whereIn($conditions[0], $conditions[2], $logic, true);
                break;
            case 'not between':
                $query->whereBetween($conditions[0], $conditions[2], $logic, true);
                break;
            default:
                $query->where(...$conditions);
        }
    }
} else {
    $query->where(function (Builder $query) use ($logic, $conditions) {
        if ('and' == $logic) {
            foreach ($conditions as $col => $val) {
                $query->where([$col => $val]);
            }
        } else {
            foreach ($conditions as $col => $val) {
                $query->orWhere([$col => $val]);
            }
        }
    });
}

}
使用示例
简单的and条件

$conditions = [

'name' => 'lily',
'sex'   => 'f',

];
$conditions = [

'name' => 'lily',
'sex'   => ['f', 'm'],

];
简单的or条件

$conditions = [

'name' => 'lily',
'sex'   => ['f', 'm'],
'or'

];
复杂的and/or查询

$conditions = [

[
    ['id', '>', 5],
    ['hobby', 'in', ['football', 'swimming']],
    ['created_at', 'between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
],
[
    ['id', '>', 5],
    ['hobby', 'in', ['football', 'swimming']],
    ['created_at', 'between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
],

];//组1 and 组2
$conditions = [

[
    ['id', '=', 5],
    ['hobby', 'in', ['football', 'swimming']],
    ['created_at', 'between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
    'or'//组1的内部做 or
],
[
    ['id', '>', 5],
    ['hobby', 'not in', ['football', 'swimming']],
    ['created_at', 'not between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
],
'or',//组1 or 组2

];
$conditions = [

'sex' => ['f', 'm'],//没问题,只要表达式的语义正确,只要你头不晕,就能混拼,
['name', '=', 'test'],
[
    ['id', '>', 5],
    ['hobby', 'in', ['football', 'swimming']],
    ['created_at', 'between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
    'or'//组1的内部做 or
],
[
    ['id', '>', 5],
    ['hobby', 'in', ['football', 'swimming']],
    ['created_at', 'between', [strtotime('2020-05-20 10:38:41'), strtotime('2021-05-25 10:39:41')]],
],
'or',//组1 or 组2

];
使用实例
// < 8.0
$query = User::select("*");//主要是拿到 Builder 对象
// $query 是对象 引用传值
User::renderWhereMixedEloquent($query, $conditions);
$query->get();

// 8.0
$query = User::query();
// $query 是对象 引用传值
User::renderWhereMixedEloquent($query, $conditions);
$query->get();


慷慨的麦片
1 声望0 粉丝