修改查询助手

This commit is contained in:
mzl
2025-07-22 19:30:27 +08:00
parent b53cfe6bf7
commit 283b21b1f8
3 changed files with 122 additions and 54 deletions
+99 -32
View File
@@ -24,6 +24,7 @@ use support\exception\BusinessException;
class CrudUtil
{
/**
* 构建查询,支持:
* - 本表字段过滤 where
@@ -56,48 +57,62 @@ class CrudUtil
$model = new $config['model'];
$q = $model->newQuery();
// 1. eager load
if (!empty($config['with'])) {
$q->with($config['with']);
}
// 2. 关联表字段选择
if (!empty($config['withFields'])) {
foreach ($config['withFields'] as $rel => $fields) {
$q->with([$rel => function ($qr) use ($fields) {
$fk = $qr->getModel()->getForeignKey();
$qr->select(array_unique(array_merge($fields, [$fk])));
}]);
// eager-load:支持 ['rel','rel2'] 和 ['rel'=>fields[], ...]
if (! empty($config['with'])) {
foreach ($config['with'] as $rel => $fields) {
if (is_int($rel)) {
// 普通关联
$q->with($fields);
} else {
// 带字段筛选的关联
$q->with([$rel => function ($qr) use ($fields) {
$key = $qr->getModel()->getKeyName();
if (! in_array($key, $fields, true)) {
$fields[] = $key;
}
$qr->select($fields);
}]);
}
}
}
// 3. 本表字段选择
// 表字段
if (!empty($config['fields'])) {
$q->select($config['fields']);
}
// 4. where 条件(支持 dot-notation 关联过滤)
// where
if (!empty($config['where'])) {
foreach ($config['where'] as $col => $val) {
if (strpos($col, '.') !== false) {
[$rel, $relCol] = explode('.', $col, 2);
$q->whereHas($rel, function ($qr) use ($relCol, $val) {
self::applyWhere($qr, $relCol, $val);
});
// 多层支持
$segments = explode('.', $col);
$leaf = array_pop($segments);
self::applyNestedWhere($q, $segments, $leaf, $val);
} else {
self::applyWhere($q, $col, $val);
}
}
}
// 5. 排序
// or where
if (!empty($config['orWhere'])) {
$q->where(function($q) use($config) {
foreach ($config['orWhere'] as $cond) {
[$col,$op,$val] = $cond;
$q->orWhere($col,$op,$val);
}
});
}
// 排序
if (!empty($config['order'])) {
foreach ($config['order'] as $col => $dir) {
$q->orderBy($col, strtolower($dir) === 'asc' ? 'asc' : 'desc');
}
}
// 6. 数据权限过滤
// 数据权限过滤
if (!empty($config['dataLimit'])) {
self::applyDataLimit($q, $config['dataLimit']);
}
@@ -261,8 +276,29 @@ class CrudUtil
//=================== Internal Methods ===================//
/**
* 应用单字段 where 过滤
* 支持多层的 whereHas:$relations=['roles','permissions'],$leaf='name'
*/
protected static function applyNestedWhere(Builder $q, array $relations, string $leaf, $val): void
{
$rel = array_shift($relations);
$q->whereHas($rel, function (Builder $qr) use ($relations, $leaf, $val) {
if ($relations) {
// 还有更深层,继续递归
self::applyNestedWhere($qr, $relations, $leaf, $val);
} else {
// 最后一层,使用普通 applyWhere
self::applyWhere($qr, $leaf, $val);
}
});
}
/**
* 单字段 where 支持:
* - 多条件数组 [ [op1,val1], [op2,val2], … ]
* - 单条件 ['op', val]
* - 直接值
*
* @param Builder $q
* @param string $col
@@ -271,22 +307,53 @@ class CrudUtil
*/
protected static function applyWhere(Builder $q, string $col, $val): void
{
if (is_array($val) && count($val) === 2) {
[$op, $v] = $val;
switch (strtolower($op)) {
case 'like': $q->where($col,'like',$v); break;
case 'in': $q->whereIn($col,(array)$v); break;
case 'not in': $q->whereNotIn($col,(array)$v); break;
case 'null': $q->whereNull($col); break;
case 'not null': $q->whereNotNull($col); break;
case 'between': $q->whereBetween($col,(array)$v); break;
default: $q->where($col,$op,$v);
// 多条件数组
if (is_array($val) && isset($val[0]) && is_array($val[0])) {
foreach ($val as $pair) {
if (is_array($pair) && count($pair) === 2) {
self::applySingleWhere($q, $col, $pair[0], $pair[1]);
}
}
} else {
}
// 单条件
elseif (is_array($val) && count($val) === 2) {
self::applySingleWhere($q, $col, $val[0], $val[1]);
}
// 直接等值
else {
$q->where($col, $val);
}
}
/**
* 真正执行一个条件的 where
*/
protected static function applySingleWhere(Builder $q, string $col, string $op, $v): void
{
switch (strtolower($op)) {
case 'like':
$q->where($col, 'like', $v);
break;
case 'in':
$q->whereIn($col, (array)$v);
break;
case 'not in':
$q->whereNotIn($col, (array)$v);
break;
case 'null':
$q->whereNull($col);
break;
case 'not null':
$q->whereNotNull($col);
break;
case 'between':
$q->whereBetween($col, (array)$v);
break;
default:
$q->where($col, $op, $v);
}
}
/**
* 应用数据权限过滤到查询(buildQuery 场景)
*/