value, // 直接查询(=) * 'scope:method' => value, // 调用模型 scope 方法 * 'relation.field' => value, // 关联模型字段查询 * 'date_range:field' => [ // 日期范围 * 'start' => value1, * 'end' => value2, * ], * 'or' => [ // OR 条件组 * ['field1' => value1], * ['field2' => value2] * ] * ] * @param array $options = [ * 'search' => value, // 搜索词 * 'searchable' => [ // 可搜索字段(支持关联字段) * 'field', // 当前模型字段搜索 * 'relation.field', // 关联模型字段搜索 * ], * 'sort_by' => 'field', // 排序字段 * 'sort_order' => 'asc/desc' // 排序方向(asc:升序、desc:降序) * ] * @return Builder */ public function scopeApplyFilters(Builder $query, array $filters = [], array $options = []): Builder { // 处理筛选条件 foreach ($filters as $field => $value) { // 跳过空值 if (is_null($value)) continue; // 动态解析筛选类型 switch (true) { case Str::startsWith($field, 'scope:'): $this->applyScopeFilter($query, $field, $value); break; case Str::contains($field, '.'): $this->applyRelationFilter($query, $field, $value); break; case Str::startsWith($field, 'date_range:'): $this->applyDateRangeFilter($query, $field, $value); break; case $field === 'or': $this->applyOrConditions($query, $value); break; default: $this->applyDefaultFilter($query, $field, $value); } } // 处理全局搜索 if (!empty($options['search']) && !empty($options['searchable'])) { $this->applyGlobalSearch($query, $options['search'], $options['searchable']); } // 处理排序 $this->applySorting($query, $options); return $query; } /** * 应用 Scope 方法筛选 */ protected function applyScopeFilter(Builder $query, string $field, $value): void { $scopeMethod = Str::after($field, 'scope:'); if (method_exists($this, 'scope' . Str::studly($scopeMethod))) { $query->{$scopeMethod}($value); } else { // 记录未知 Scope 方法 logger()->warning("Undefined scope method: {$scopeMethod}"); } } /** * 应用关联模型筛选 */ protected function applyRelationFilter(Builder $query, string $field, $value): void { [$relation, $relationField] = explode('.', $field, 2); $query->whereHas($relation, function ($q) use ($relationField, $value) { $q->where($relationField, $value); }); } /** * 应用日期范围筛选 */ protected function applyDateRangeFilter(Builder $query, string $field, array $value): void { $dataRangeField = Str::after($field, 'date_range:'); if (isset($value['start']) && isset($value['end'])) { $start = Carbon::parse($value['start'])->startOfDay(); $end = Carbon::parse($value['end'])->endOfDay(); $query->whereBetween($dataRangeField, [$start, $end]); } } /** * 应用 OR 条件组 */ protected function applyOrConditions(Builder $query, array $conditions): void { $query->where(function ($q) use ($conditions) { foreach ($conditions as $group) { $q->orWhere(function ($subQ) use ($group) { foreach ($group as $field => $value) { $subQ->where($field, $value); } }); } }); } /** * 应用默认筛选(= 条件) */ protected function applyDefaultFilter(Builder $query, string $field, $value): void { $query->where($field, $value); } /** * 全局模糊搜索 */ protected function applyGlobalSearch(Builder $query, string $searchTerm, array $searchableFields): void { $query->where(function ($q) use ($searchTerm, $searchableFields) { foreach ($searchableFields as $field) { if (Str::contains($field, '.')) { $this->applyRelationSearch($q, $field, $searchTerm); } else { $q->orWhere($field, 'LIKE', "%{$searchTerm}%"); } } }); } /** * 处理关联字段搜索 */ protected function applyRelationSearch(Builder $query, string $field, string $searchTerm): void { $relations = explode('.', $field); $column = array_pop($relations); $relation = implode('.', $relations); $query->orWhereHas($relation, function ($q) use ($column, $searchTerm) { $q->where($column, 'LIKE', "%{$searchTerm}%"); }); } /** * 应用排序逻辑 */ protected function applySorting(Builder $query, array $options): void { $sortBy = $options['sort_by'] ?? 'id'; $sortOrder = $options['sort_order'] ?? 'desc'; $query->orderBy($sortBy, $sortOrder); } }