Skip to content

Commit 0449581

Browse files
author
Marius
committed
update list: add basic filtering and multi sort on the resource's columns
1 parent 80ab2ea commit 0449581

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ The relations will be retrieved as well when required. The relation keys CAN'T b
188188
```pivot``` is optional and appears only on relations that are tied via a pivot.
189189

190190
#### I.3 List filtered resource
191-
**GET** /{resource}?page=1&limit=10 // filters are available only in the paid version
191+
**GET** /{resource}?page=1&limit=10&column=2&sort[0][by]=updated_at&sort[0][dir]=ASC // advanced filters and aggregations are available only in the paid version
192192

193193
**GET** /{resource}/{identifier}/{relation}?... // available only in paid version
194194

@@ -233,14 +233,16 @@ The reserved words / parameters that will be used as query params are:
233233
page,
234234
limit,
235235
simplePaginate
236-
cursor
236+
cursor,
237+
sort
237238

238239
Defaults:
239240

240241
page=1;
241242
limit=10;
242243
simplePaginate is false by default and only its presence is checked in request, not its value
243244
cursor is not defined
245+
sort[dir]=DESC
244246

245247
Obs.
246248

src/Models/BaseModel.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,18 @@ public function getColumnIndex(string $column, bool $asFirst = false): string
236236
return $collection->firstOrFail()->Key_name;
237237
}
238238

239+
public function getIndexedColumns(bool $includingPrimary = true): array
240+
{
241+
return $includingPrimary ?
242+
$this->retrieveFirstSeqIndexedColumns() :
243+
\array_diff($this->retrieveFirstSeqIndexedColumns(), [$this->primaryKey]);
244+
}
245+
246+
public function isIndexRequiredOnFiltering(): bool
247+
{
248+
return $this->indexRequiredOnFiltering;
249+
}
250+
239251
/**
240252
* @inheritDoc
241253
*/

src/Services/BaseResourceService.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,43 @@ public function update(string $identifier, array $request): BaseModel
8080
*/
8181
public function list(array $request): Builder
8282
{
83-
return $this->model::query();
83+
$builder = $this->model::query();
84+
$filters = GeneralHelper::filterDataByKeys($request, $possibleSortColumns = $this->model->getColumns());
85+
86+
if ($this->model->isIndexRequiredOnFiltering()) {
87+
$possibleSortColumns = $this->model->getIndexedColumns();
88+
89+
if (
90+
$filters !== []
91+
&& [] === \array_filter(
92+
GeneralHelper::filterDataByKeys($filters, $possibleSortColumns),
93+
fn (mixed $filter): bool => !\is_array($filter)
94+
)
95+
) {
96+
throw new \Exception('Ignoring filters');
97+
}
98+
}
99+
100+
foreach ($filters as $column => $value) {
101+
if (!\is_array($value)) {
102+
$builder->where($column, '=', $value);
103+
}
104+
}
105+
106+
if ($this->shouldIgnoreSort($possibleSortColumns)) {
107+
return $builder;
108+
}
109+
110+
foreach ((array)($request['sort'] ?? []) as $orderBy) {
111+
if (\in_array($orderBy['by'] ?? '', $possibleSortColumns, true)) {
112+
$builder->orderBy(
113+
$orderBy['by'],
114+
\strtoupper($orderBy['dir'] ?? '') === 'ASC' ? 'ASC' : 'DESC'
115+
);
116+
}
117+
}
118+
119+
return $builder;
84120
}
85121

86122
/**
@@ -151,4 +187,15 @@ protected function extractIdentifierConditions(string $identifier): array
151187
[$this->model->getKeyName(), $identifier]
152188
];
153189
}
190+
191+
protected function shouldIgnoreSort(array $possibleSortColumns): bool
192+
{
193+
foreach ($this->request['sort'] ?? [] as $sort) {
194+
if (isset($sort['by'])) {
195+
return !\in_array($sort['by'], $possibleSortColumns, true);
196+
}
197+
}
198+
199+
return true;
200+
}
154201
}

0 commit comments

Comments
 (0)