1

Personally, I feel Eloquent ORM the where not so rich, and the assembly of many conditions requires the introduction of additional orWhere, whereNotIn, whereBetween, whereNotBetween to assist in completion. This is not very friendly when doing some abstract low-level query methods. The query conditions passed by the upper layer are uncertain. If you can flexibly analyze various mixed query conditions (described in an array), it will be more efficient to use Be flexible.

/**
 * 渲染复杂的 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]);
                }
            }
        });
    }
}

Example of use

simple and conditions

$conditions = [
    'name' => 'lily',
    'sex'   => 'f',
];
$conditions = [
    'name' => 'lily',
    'sex'   => ['f', 'm'],
];

simple or condition

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

complex and/or query

$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
];

Use case

// < 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();

big_cat
1.7k 声望130 粉丝

规范至上