$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); } }