Skip to content

Commit d4c2c04

Browse files
authored
Sub search for relations added #minor (#29)
* Sub search for relations added * Apply fixes from StyleCI * Minor
1 parent 5f3367f commit d4c2c04

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,22 @@ Will perform ``SELECT * FROM some_table WHERE first_name IN
143143
Note that logical operators are using standard bool logic precedence,
144144
therefore ``x AND y OR z AND q`` is the same as `(x AND y) OR (z AND q)`.
145145

146+
#### Nested relation searches
147+
148+
You can nest another search object if the key used is a relation name which
149+
will execute a ``whereHas()`` query builder method.
150+
151+
I.e.
152+
```
153+
{
154+
"search": {
155+
"some_relation": {
156+
"search": { ... }
157+
},
158+
}
159+
}
160+
```
161+
146162
### Returns
147163

148164
Using a ``returns`` key will effectively only return the fields given within it.

src/RequestParameters/SearchParameter.php

+24-6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66

77
use Asseco\JsonQueryBuilder\Config\OperatorsConfig;
88
use Asseco\JsonQueryBuilder\Exceptions\JsonQueryBuilderException;
9+
use Asseco\JsonQueryBuilder\JsonQuery;
910
use Asseco\JsonQueryBuilder\SearchCallbacks\AbstractCallback;
1011
use Asseco\JsonQueryBuilder\SearchParser;
1112
use Illuminate\Database\Eloquent\Builder;
13+
use Illuminate\Support\Str;
1214

1315
class SearchParameter extends AbstractParameter
1416
{
@@ -31,6 +33,7 @@ public static function getParameterName(): string
3133
protected function appendQuery(): void
3234
{
3335
$arguments = $this->arguments;
36+
3437
$this->operatorsConfig = new OperatorsConfig();
3538

3639
// Wrapped within a where clause to protect from orWhere "exploits".
@@ -50,27 +53,35 @@ protected function appendQuery(): void
5053
protected function makeQuery(Builder $builder, array $arguments, string $boolOperator = self:: AND): void
5154
{
5255
foreach ($arguments as $key => $value) {
53-
if ($this->isBoolOperator($key)) {
54-
// Recursion for keys which are &&/||
56+
if ($this->isTopLevelBoolOperator($key)) {
5557
$this->makeQuery($builder, $value, $key);
5658
continue;
5759
}
5860

5961
$functionName = $this->getQueryFunctionName($boolOperator);
6062

61-
if ($this->shouldSplitQueries($value)) {
63+
if ($this->queryInitiatedByTopLevelBool($key, $value)) {
6264
$builder->{$functionName}(function ($queryBuilder) use ($value) {
6365
// Recursion for inner keys which are &&/||
6466
$this->makeQuery($queryBuilder, $value);
6567
});
6668
continue;
6769
}
6870

71+
if ($this->hasSubSearch($key, $value)) {
72+
// If query has sub-search, it is a relation for sure.
73+
$builder->whereHas(Str::camel($key), function ($query) use ($value) {
74+
$jsonQuery = new JsonQuery($query, $value);
75+
$jsonQuery->search();
76+
});
77+
continue;
78+
}
79+
6980
$this->makeSingleQuery($functionName, $builder, $key, $value);
7081
}
7182
}
7283

73-
protected function isBoolOperator($key): bool
84+
protected function isTopLevelBoolOperator($key): bool
7485
{
7586
return in_array($key, [self:: OR, self:: AND], true);
7687
}
@@ -91,9 +102,16 @@ protected function getQueryFunctionName(string $boolOperator): string
91102
throw new JsonQueryBuilderException('Invalid bool operator provided');
92103
}
93104

94-
protected function shouldSplitQueries($value): bool
105+
protected function queryInitiatedByTopLevelBool($key, $value): bool
106+
{
107+
// Since this will be triggered by recursion, key will be numeric
108+
// and not the actual key.
109+
return !is_string($key) && is_array($value);
110+
}
111+
112+
protected function hasSubSearch($key, $value): bool
95113
{
96-
return is_array($value);
114+
return is_string($key) && is_array($value);
97115
}
98116

99117
/**

0 commit comments

Comments
 (0)