Skip to content

Commit 632d3c2

Browse files
committed
fix: search improve
1 parent e37cc22 commit 632d3c2

File tree

5 files changed

+57
-11
lines changed

5 files changed

+57
-11
lines changed

UPGRADING.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,52 @@ class UserRepository extends Repository
119119

120120
This change is also **100% backward compatible** - existing static arrays continue to work perfectly.
121121

122+
## Breaking Changes
123+
124+
### Default Search Behavior Change
125+
126+
🚨 **Breaking Change**: In version 10, repositories no longer search by the model's primary key (ID) by default when no searchable fields are defined.
127+
128+
**Before (v9 and earlier):**
129+
```php
130+
class UserRepository extends Repository
131+
{
132+
// No $search property defined
133+
// Automatically searched by 'id' field by default
134+
}
135+
```
136+
137+
**After (v10):**
138+
```php
139+
class UserRepository extends Repository
140+
{
141+
// No $search property defined
142+
// No searchable fields available - search returns empty results
143+
}
144+
```
145+
146+
**To maintain the previous behavior**, add this method to your Repository parent class or individual repositories:
147+
148+
```php
149+
public static function searchables(): array
150+
{
151+
return empty(static::$search)
152+
? [static::newModel()->getKeyName()]
153+
: static::$search;
154+
}
155+
```
156+
157+
**Why this change was made:**
158+
- **Security**: Prevents unintended ID-based searches on sensitive repositories
159+
- **Explicit configuration**: Forces developers to explicitly define searchable fields
160+
- **Performance**: Avoids unnecessary database queries when search isn't intended
161+
- **Consistency**: Aligns with the principle of explicit over implicit behavior
162+
163+
**Migration strategy:**
164+
1. **Immediate fix**: Add the `searchables()` method to your base Repository class to restore v9 behavior globally
165+
2. **Recommended approach**: Review each repository and explicitly define `$search` arrays with appropriate fields
166+
3. **Security review**: Consider which repositories should actually be searchable and by which fields
167+
122168
### Configuration File Updates
123169

124170
When upgrading to v10, it's important to ensure your local `config/restify.php` file includes all the new configuration options that have been added.

src/Filters/SearchableFilter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ public function filter(RestifyRequest $request, $query, $value)
2727
$likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like';
2828

2929
if (isset($this->belongsToField)) {
30+
ray('Searching through BelongsTo relation');
3031
if (! $this->belongsToField->authorize($request)) {
32+
ray('BelongsTo field not authorized for this request, skipping search.');
3133
return $query;
3234
}
3335

src/Filters/SearchablesCollection.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,8 @@ public function __construct($items = [])
2828
} elseif ($searchable instanceof Filter) {
2929
// Other Filter instance - keep it
3030
$unified[] = $searchable;
31-
} elseif (is_callable($searchable)) {
32-
// Closure or invokable - create SearchableFilter with closure
33-
$filter = new SearchableFilter;
34-
$filter->usingClosure($searchable);
35-
$filter->setColumn(is_string($key) && ! is_numeric($key) ? $key : 'unknown');
36-
$unified[] = $filter;
3731
} elseif (is_string($searchable)) {
38-
// String column name
32+
// String column name (including string callables like "MyClass::method")
3933
$filter = new SearchableFilter;
4034
$filter->setColumn($searchable);
4135
$unified[] = $filter;
@@ -44,6 +38,12 @@ public function __construct($items = [])
4438
$filter = new SearchableFilter;
4539
$filter->setColumn($key);
4640
$unified[] = $filter;
41+
} elseif (is_callable($searchable)) {
42+
// Non-string callables (closures, arrays, invokables)
43+
$filter = new SearchableFilter;
44+
$filter->usingClosure($searchable);
45+
$filter->setColumn(is_string($key) && ! is_numeric($key) ? $key : 'unknown');
46+
$unified[] = $filter;
4747
}
4848
}
4949

src/Repositories/Repository.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class Repository implements JsonSerializable, RestifySearchable
125125
/**
126126
* The list of searchable fields.
127127
*/
128-
public static array $search;
128+
public static array $search = [];
129129

130130
/**
131131
* The list of matchable fields.

src/Traits/InteractWithSearch.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ trait InteractWithSearch
2727

2828
public static function searchables(): array
2929
{
30-
return empty(static::$search)
31-
? [static::newModel()->getKeyName()]
32-
: static::$search;
30+
return static::$search;
3331
}
3432

3533
public static function withs(): array

0 commit comments

Comments
 (0)