Skip to content

Commit cb63f60

Browse files
authored
[Feature] Add filtering to /meta endpoint (#87)
1 parent 6f6c7cc commit cb63f60

File tree

5 files changed

+305
-50
lines changed

5 files changed

+305
-50
lines changed

app/Http/Controllers/Api/V1/GetBreweriesMeta.php

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,55 @@
33
namespace App\Http\Controllers\Api\V1;
44

55
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\V1\BreweryFilterRequest;
67
use App\Http\Resources\V1\BreweryMetaResource;
78
use App\Models\Brewery;
8-
use Illuminate\Http\Request;
99
use Illuminate\Http\Response;
10-
use Illuminate\Support\Facades\Cache;
1110
use Illuminate\Support\Facades\DB;
1211

1312
class GetBreweriesMeta extends Controller
1413
{
1514
/**
1615
* Handle the incoming request.
1716
*/
18-
public function __invoke(Request $request)
17+
public function __invoke(BreweryFilterRequest $request)
1918
{
20-
$data = Cache::remember('brewery_meta', 300, function () {
21-
$total = Brewery::count();
22-
23-
$byState = Brewery::query()
24-
->select('state_province', DB::raw('count(*) as count'))
25-
->whereNotNull('state_province')
26-
->groupBy('state_province')
27-
->pluck('count', 'state_province')
28-
->toArray();
29-
$byType = Brewery::query()
30-
->select('brewery_type', DB::raw('count(*) as count'))
31-
->whereNotNull('brewery_type')
32-
->groupBy('brewery_type')
33-
->pluck('count', 'brewery_type')
34-
->mapWithKeys(function ($count, $type) {
35-
return [strtolower($type) => $count];
36-
})
37-
->toArray();
38-
39-
return new BreweryMetaResource([
40-
'total' => $total,
41-
'by_state' => $byState,
42-
'by_type' => $byType,
43-
]);
44-
});
19+
20+
// Create a base query that applies filters
21+
$baseQuery = Brewery::query()->applyFilters($request);
22+
23+
// Get total count with filters applied
24+
$total = $baseQuery->count();
25+
26+
// Get by_state with filters applied
27+
$byState = (clone $baseQuery)
28+
->select('state_province', DB::raw('count(*) as count'))
29+
->whereNotNull('state_province')
30+
->groupBy('state_province')
31+
->pluck('count', 'state_province')
32+
->toArray();
33+
34+
// Get by_type with filters applied
35+
$byType = (clone $baseQuery)
36+
->select('brewery_type', DB::raw('count(*) as count'))
37+
->whereNotNull('brewery_type')
38+
->groupBy('brewery_type')
39+
->pluck('count', 'brewery_type')
40+
->mapWithKeys(function ($count, $type) {
41+
return [strtolower($type) => $count];
42+
})
43+
->toArray();
44+
45+
$page = $request->integer('page', 1);
46+
$perPage = $request->integer('per_page', 50);
47+
48+
$data = new BreweryMetaResource([
49+
'total' => $total,
50+
'by_state' => $byState,
51+
'by_type' => $byType,
52+
'page' => $page,
53+
'per_page' => $perPage,
54+
]);
4555

4656
return response()->json(
4757
data: $data,

app/Http/Controllers/Api/V1/ListBreweries.php

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,18 @@
33
namespace App\Http\Controllers\Api\V1;
44

55
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\V1\BreweryFilterRequest;
67
use App\Http\Resources\V1\BreweryResource;
78
use App\Models\Brewery;
8-
use App\Rules\BreweryType as BreweryTypeRule;
9-
use App\Rules\Coordinates as CoordinatesRule;
10-
use Illuminate\Http\Request;
119
use Illuminate\Http\Response;
1210

1311
class ListBreweries extends Controller
1412
{
1513
/**
1614
* Handle the incoming request.
1715
*/
18-
public function __invoke(Request $request)
16+
public function __invoke(BreweryFilterRequest $request)
1917
{
20-
$request->validate([
21-
'per_page' => ['sometimes', 'required', 'integer', 'min:1', 'max:200'],
22-
'page' => ['integer', 'min:1'],
23-
'sort' => ['string'],
24-
25-
// filters
26-
'by_city' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
27-
'by_country' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
28-
'by_dist' => ['sometimes', 'required', 'string', new CoordinatesRule],
29-
'by_ids' => ['sometimes', 'required', 'string', 'min:3', 'max:255'], // ! this aint right, need to validate as array and that they're uuid v4
30-
'by_name' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
31-
'by_postal' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
32-
'by_state' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
33-
'by_type' => ['sometimes', 'required', 'string', new BreweryTypeRule],
34-
'exclude_types' => ['sometimes', 'required', 'string', new BreweryTypeRule],
35-
]);
3618

3719
$breweries = Brewery::query()
3820
->applyFilters($request)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace App\Http\Requests\V1;
4+
5+
use App\Rules\BreweryType as BreweryTypeRule;
6+
use App\Rules\Coordinates as CoordinatesRule;
7+
use Illuminate\Foundation\Http\FormRequest;
8+
9+
class BreweryFilterRequest extends FormRequest
10+
{
11+
/**
12+
* Determine if the user is authorized to make this request.
13+
*/
14+
public function authorize(): bool
15+
{
16+
return true;
17+
}
18+
19+
/**
20+
* Get the validation rules that apply to the request.
21+
*
22+
* @return array<string, mixed>
23+
*/
24+
public function rules(): array
25+
{
26+
return [
27+
'per_page' => ['sometimes', 'required', 'integer', 'min:1', 'max:200'],
28+
'page' => ['sometimes', 'required', 'integer', 'min:1'],
29+
'sort' => ['sometimes', 'required', 'string'],
30+
31+
// filters
32+
'by_city' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
33+
'by_country' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
34+
'by_dist' => ['sometimes', 'required', 'string', new CoordinatesRule],
35+
'by_ids' => ['sometimes', 'required', 'string', 'min:3', 'max:255'], // TODO: validate as array of uuid v4
36+
'by_name' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
37+
'by_postal' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
38+
'by_state' => ['sometimes', 'required', 'string', 'min:3', 'max:255'],
39+
'by_type' => ['sometimes', 'required', 'string', new BreweryTypeRule],
40+
'exclude_types' => ['sometimes', 'required', 'string', new BreweryTypeRule],
41+
];
42+
}
43+
}

app/Http/Resources/V1/BreweryMetaResource.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public function toArray(Request $request): array
1818
'total' => $this->resource['total'],
1919
'by_state' => $this->resource['by_state'],
2020
'by_type' => $this->resource['by_type'],
21+
'page' => $this->resource['page'] ?? 1,
22+
'per_page' => $this->resource['per_page'] ?? 50,
2123
];
2224
}
2325
}

0 commit comments

Comments
 (0)