| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- <?php
- namespace App\Traits;
- use Carbon\Carbon;
- use Illuminate\Database\Eloquent\Builder;
- use Illuminate\Support\Str;
- trait Filterable
- {
- /**
- * 通用筛选方法(支持多场景)
- *
- * @param Builder $query
- * @param array $filters = [
- * 'field' => 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);
- }
- }
|