Animal as a fully protected resource (JWT + scopes).
Directory layout
1. Declare the resource
Route::resource() uses getBaseUrl() + getPluralName() to build URLs: /api/v1/animals and /api/v1/animals/{animal_uuid}.
2. Wire the five controllers
Each controller is a thin subclass. The base class fills in the route, request class, response classes, and OpenAPI schema.Create
View
Update
Delete
List
What the framework handles for you
- URL + verb per mode —
Route::resource()picksPOST /api/v1/animals,GET /api/v1/animals/{animal_uuid},PATCHfor update,DELETEfor delete,GETcollection for list. You can’t accidentally violate REST conventions. - Body / path / filter / sort validation —
RequestValidationMiddlewarevalidates against the runtime documentation derived fromAnimalResource. Unknown?order_by=hacked_field→ 422 before your controller runs. - Response envelope —
Resource*Responseclasses emit the standard{"data": ...}(and"pagination"for list). NotoArray()to write. - Per-mode field visibility —
excludeFromMode()hidesweightfrom the list endpoint; the rest of the endpoints still see it. - OpenAPI — all five operations are generated from the single resource. Add a field to
AnimalResource::init()and every operation updates at once.
Optional: IDE autocomplete via the DocBlock generator
Run the docblock generator once to emit@property annotations on AnimalResource and typed request stubs (AnimalListRequest) for filters and sorts. See Generate OpenAPI and docblocks for the script.
After the generator runs, $animal->name, $request->filtering()->status, and $request->sorting()->created_at all autocomplete.