个人感觉 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::renderWhere($query, $conditionsSub);
});
}
});
} else {
$query->where(function (Builder $query) use ($conditions) {
foreach ($conditions as $conditionsSub) {
$query->where(function (Builder $query) use ($conditionsSub) {
static::renderWhere($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();
发表回复