65 lines
1.9 KiB
PHP
65 lines
1.9 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
namespace app\mzl\common\utils;
|
|||
|
|
|
|||
|
|
class SearchHelper
|
|||
|
|
{
|
|||
|
|
public static function parseFiltersAndRelations(array $params, array $mapping): array
|
|||
|
|
{
|
|||
|
|
$filters = [];
|
|||
|
|
$relations = [];
|
|||
|
|
$hasRelations = [];
|
|||
|
|
|
|||
|
|
// 解析过滤条件和关联字段
|
|||
|
|
foreach ($mapping as $paramKey => $definition) {
|
|||
|
|
$field = $definition['field'];
|
|||
|
|
$operator = $definition['operator'];
|
|||
|
|
$value = $params[$paramKey] ?? null;
|
|||
|
|
|
|||
|
|
if (self::isValidValue($value, $operator)) {
|
|||
|
|
$filters[] = compact('field', 'operator', 'value');
|
|||
|
|
if (str_contains($field, '.')) {
|
|||
|
|
$relations[] = self::extractRelationPath($field);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 解析 whereHas 关联字段(如 profile.age)
|
|||
|
|
foreach ($params as $key => $value) {
|
|||
|
|
if (str_contains($key, '.')) {
|
|||
|
|
$relation = explode('.', $key)[0]; // 获取关联名
|
|||
|
|
$hasRelations[$relation] = function ($query) use ($key, $value) {
|
|||
|
|
$query->where($key, '=', $value);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return [
|
|||
|
|
'filters' => $filters,
|
|||
|
|
'relations' => array_unique($relations),
|
|||
|
|
'hasRelations' => $hasRelations,
|
|||
|
|
];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static function isValidValue(mixed $value, string $operator): bool
|
|||
|
|
{
|
|||
|
|
$operator = strtolower($operator);
|
|||
|
|
|
|||
|
|
if (in_array($operator, ['in', 'not_in', 'between'])) {
|
|||
|
|
return is_array($value) && !empty($value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (in_array($operator, ['null', 'not_null'])) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return $value !== '' && $value !== null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static function extractRelationPath(string $field): string
|
|||
|
|
{
|
|||
|
|
$parts = explode('.', $field);
|
|||
|
|
array_pop($parts);
|
|||
|
|
return implode('.', $parts);
|
|||
|
|
}
|
|||
|
|
}
|