Eloquent ORM 的 where 查询条件的解析器增强版
个人感觉 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();
推荐阅读
C4模型的绘制及示例
环境准备VsCode + PlantUML插件 {代码...} 相关文献C4 模型 - 可视化架构设计使用PlantUML绘制C4模型风格的软件架构图C4 model技术架构图--context图代码示例 {代码...}
big_cat阅读 34
一文快速入门体验 Hibernate
Hibernate 是一个优秀的持久层的框架,当然,虽然现在说用得比较多的是 MyBaits,但是我工作中也不得不接触 Hibernate,特别是一些老项目需要你维护的时候。所以,在此写下这篇文章,方便自己回顾,也方便新手入...
god23bin赞 2阅读 491
Springboot 撞上 NebulaGraph——NGbatis 初体验
大家好,我是开源项目 NGbatis 的发起人大叶(CorvusYe@GitHub)。目前 NGbatis 也已成为 NebulaGraph 开源生态项目之一。在过去的 4 个月里,NGbatis 从提交第一行代码以来,已经发布了 3 个版本,正在一步步变...
NebulaGraph赞 2阅读 469
Goravel ORM 新增模型关联,用 Golang 写关联也可以跟 Laravel 简单
Goravel 是一个功能完备、具有良好扩展能力的 Web 应用程序框架。作为一个起始脚手架帮助 Golang 开发者快速构建自己的应用。框架风格与 Laravel 保持一致,让 PHPer 不用学习新的框架,也可以愉快的玩转 Golang!
韩同学的简单逻辑阅读 759
laravel 文档摘要
$request->input('date') 可以是 "2021-01-05 01:00:00" 字符串,通过 Carbon::parse($request->input('date') ?? now_local()),它可以被转化为 CarbonInterface::DateTimeInterface
changsj阅读 731
Ent.中文文档(持续更新~)
快速开始简介ent 是一个简单而强大的Go语言实体框架,它使得构建和维护大型数据模型的应用程序变得容易,同时ent遵循以下原则:轻松地将数据库模式建模为图形结构将模式定义为可编程的Go语言代码基于代码生成的静...
sayornottt阅读 726
【第五篇Laravel10权限中间件】Laravel10 + Vue3.0前后端分离框架通用后台源码
②复制Laravel9 + Vue3.0前后端分离框架通用后台源码,backend/app/Http/Kernel.php 搜索 $routeMiddleware
小拼拼阅读 597
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。