diff --git a/src/Filters/SearchableFilter.php b/src/Filters/SearchableFilter.php index 39f34f147..731faa1f5 100644 --- a/src/Filters/SearchableFilter.php +++ b/src/Filters/SearchableFilter.php @@ -24,18 +24,34 @@ public function filter(RestifyRequest $request, $query, $value) return $query; } - // This approach could be rewritten using join. - collect($this->belongsToField->getSearchables())->each(function (string $attribute) use ($query, $likeOperator, $value) { - $query->orWhere( - $this->belongsToField->getRelatedModel($this->repository)::select($attribute) - ->whereColumn( - $this->belongsToField->getQualifiedKey($this->repository), - $this->belongsToField->getRelatedKey($this->repository) - ) - ->take(1), - $likeOperator, - "%{$value}%" - ); + $relatedModel = $this->belongsToField->getRelatedModel($this->repository); + $relatedTable = $relatedModel->getTable(); + $localKey = $this->belongsToField->getRelatedKey($this->repository); + $foreignKey = $this->belongsToField->getQualifiedKey($this->repository); + + // Check if we already joined this table + $hasJoin = collect($query->getQuery()->joins ?? [])->contains(function ($join) use ($relatedTable, $localKey, $foreignKey) { + return $join->table === $relatedTable + && collect($join->wheres)->contains(function ($where) use ($localKey, $foreignKey) { + return isset($where['first']) && isset($where['second']) + && $where['first'] === $foreignKey + && $where['second'] === $localKey; + }); + }); + + if (! $hasJoin) { + $query->leftJoin($relatedTable, $foreignKey, '=', $localKey); + } + + // Apply search conditions using the joined table + collect($this->belongsToField->getSearchables())->each(function (string $attribute) use ($query, $relatedTable, $likeOperator, $value) { + $columnName = $relatedTable.'.'.$attribute; + + if (! config('restify.search.case_sensitive')) { + $query->orWhereRaw("UPPER({$columnName}) LIKE ?", ['%'.strtoupper($value).'%']); + } else { + $query->orWhere($columnName, $likeOperator, "%{$value}%"); + } }); return $query; diff --git a/src/Services/Search/RepositorySearchService.php b/src/Services/Search/RepositorySearchService.php index dc17c26fb..d16c574a2 100644 --- a/src/Services/Search/RepositorySearchService.php +++ b/src/Services/Search/RepositorySearchService.php @@ -156,14 +156,15 @@ public function prepareSearchFields(RestifyRequest $request, $query) ); $filter->filter($request, $query, $search); - - $this->repository::collectRelated() - ->onlySearchable($request) - ->map(function (BelongsTo $field) { - return SearchableFilter::make()->setRepository($this->repository)->usingBelongsTo($field); - }) - ->each(fn (SearchableFilter $filter) => $filter->filter($request, $query, $search)); } + + // Process related searchable fields + $this->repository::collectRelated() + ->onlySearchable($request) + ->map(function (BelongsTo $field) { + return SearchableFilter::make()->setRepository($this->repository)->usingBelongsTo($field); + }) + ->each(fn (SearchableFilter $filter) => $filter->filter($request, $query, $search)); }); return $query;