Skip to content

Commit 467d4d8

Browse files
committed
- Added nested resources docs
1 parent 09ff352 commit 467d4d8

1 file changed

Lines changed: 235 additions & 0 deletions

File tree

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
---
2+
title: Nested resource controller
3+
sidebar_position: 2
4+
---
5+
6+
To create a nested API resource controller using this package, create a controller that extends the `Javaabu\QueryBuilder\Http\Controllers\NestedApiController` class.
7+
8+
```php
9+
<?php
10+
11+
namespace App\Http\Controllers\Api;
12+
13+
use Javaabu\QueryBuilder\Http\Controllers\NestedApiController;
14+
use App\Models\Form;
15+
use App\Models\FormFields;
16+
use Illuminate\Database\Eloquent\Builder;
17+
use Spatie\QueryBuilder\AllowedFilter;
18+
19+
class FormFieldsController extends NestedApiController
20+
{
21+
public function index(Form $form, Request $request)
22+
{
23+
$this->setAdditionalParams(compact('form'));
24+
25+
return $this->indexEndpoint($request);
26+
}
27+
28+
public function show(Form $form, $model_id, Request $request)
29+
{
30+
$this->setAdditionalParams(compact('form'));
31+
32+
return $this->showEndpoint($model_id, $request);
33+
}
34+
35+
/**
36+
* Get the base query
37+
*
38+
* @return Builder
39+
*/
40+
public function getBaseQuery(): Builder
41+
{
42+
$form = $this->getAdditionalParams('form');
43+
44+
return FormFields::query()
45+
->where('form_id', $form->id);
46+
}
47+
48+
/**
49+
* Get the allowed fields
50+
*
51+
* @return array
52+
*/
53+
public function getAllowedFields(): array
54+
{
55+
return array_diff(\Schema::getColumnListing('form_fields'), (new FormField)->getHidden());
56+
}
57+
58+
/**
59+
* Get the allowed includes
60+
*
61+
* @return array
62+
*/
63+
public function getAllowedIncludes(): array
64+
{
65+
return [
66+
];
67+
}
68+
69+
/**
70+
* Get the allowed appends
71+
*
72+
* @return array
73+
*/
74+
public function getAllowedAppends(): array
75+
{
76+
return [
77+
78+
];
79+
}
80+
81+
/**
82+
* Get the allowed sorts
83+
*
84+
* @return array
85+
*/
86+
public function getAllowedSorts(): array
87+
{
88+
return [
89+
'id',
90+
'created_at',
91+
'updated_at',
92+
'slug',
93+
'name',
94+
];
95+
}
96+
97+
/**
98+
* Get the default sort
99+
*
100+
* @return string
101+
*/
102+
public function getDefaultSort(): string
103+
{
104+
return '-created_at';
105+
}
106+
107+
/**
108+
* Get the allowed filters
109+
*
110+
* @return array
111+
*/
112+
public function getAllowedFilters(): array
113+
{
114+
return [
115+
'id',
116+
'slug',
117+
'name',
118+
AllowedFilter::scope('search'),
119+
];
120+
}
121+
}
122+
```
123+
124+
For nested controllers, you will have to manually define the `index` and `show` methods, which will enable you to add dependency injection for the parent model.
125+
Use the `setAdditionalParams()` method to set the parent models.
126+
127+
```php
128+
public function index(Form $form, Request $request)
129+
{
130+
$this->setAdditionalParams([
131+
'form' => $form
132+
]);
133+
134+
return $this->indexEndpoint($request);
135+
}
136+
137+
public function show(Form $form, $model_id, Request $request)
138+
{
139+
$this->setAdditionalParams(compact('form'));
140+
141+
return $this->showEndpoint($model_id, $request);
142+
}
143+
```
144+
145+
You can use the `getAdditionalParams()` method in other methods to retrieve a previously set named parent model.
146+
147+
```php
148+
public function getBaseQuery(): Builder
149+
{
150+
$form = $this->getAdditionalParams('form');
151+
152+
return FormFields::query()
153+
->where('form_id', $form->id);
154+
}
155+
```
156+
157+
If you don't specify a parameter name for the `getAdditionalParams()` method, then it will return all the additional parameters.
158+
159+
For frequently access additional parameters, you can create helper methods in your controller with defined return types. This will also help with intellisense.
160+
161+
```php
162+
protected function getForm(): Form
163+
{
164+
return $this->getAdditionalParams('form');
165+
}
166+
167+
public function getBaseQuery(): Builder
168+
{
169+
$form = $this->getForm();
170+
171+
return FormFields::query()
172+
->where('form_id', $form->id);
173+
}
174+
```
175+
176+
Once the `index` and `show` methods are defined, you can use them to define the routes in your `api.php` route file.
177+
178+
```php
179+
// in api.php route file
180+
181+
/**
182+
* Form Fields
183+
*/
184+
Route::get('forms/{form}/fields', [\App\Controllers\Api\FormFieldsController::class, 'index'])->name('forms.fields.index');
185+
Route::get('forms/{form}/fields/{id}', [\App\Controllers\Api\FormFieldsController::class, 'show'])->name('forms.fields.show');
186+
```
187+
188+
## Multi level deep nested controllers.
189+
190+
This package does not limit how deep you can nest your API resources. But we recommend not nest more than 1 level deep.
191+
To nest more than 1 level deep, just include your parent models, in the `index` and `show` methods and add set those as additional parameters.
192+
193+
```php
194+
// FormFieldOptionsController.php
195+
196+
public function index(Form $form, FormField $field, Request $request)
197+
{
198+
$this->setAdditionalParams(compact('form', 'field'));
199+
200+
return $this->indexEndpoint($request);
201+
}
202+
203+
public function show(Form $form, FormField $field, $model_id, Request $request)
204+
{
205+
$this->setAdditionalParams(compact('form', 'field'));
206+
207+
return $this->showEndpoint($model_id, $request);
208+
}
209+
210+
public function getBaseQuery(): Builder
211+
{
212+
$form = $this->getAdditionalParams('form');
213+
214+
$field = $this->getAdditionalParams('field');
215+
216+
return FormFieldOption::query()
217+
->whereHas('formField', function (Builder $query) use ($form, $field) {
218+
$query->where('form_fields.id', $field->id)
219+
->where('form_fields.form_id', $form->id)
220+
});
221+
}
222+
```
223+
224+
Then in your `api.php` route file, you can define the routes like so:
225+
226+
```php
227+
// in api.php route file
228+
229+
/**
230+
* Form Field Options
231+
*/
232+
Route::get('forms/{form}/fields/{field}/options', [\App\Controllers\Api\FormFieldOptionsController::class, 'index'])->name('forms.fields.options.index');
233+
Route::get('forms/{form}/fields/{field}/options/{id}', [\App\Controllers\Api\FormFieldOptionsController::class, 'show'])->name('forms.fields.options.show');
234+
```
235+

0 commit comments

Comments
 (0)