Animal as a fully protected resource (JWT + scopes).
Directory layout
1. Declare the resource
animal_uuid) is a regular property declared first by convention. Excluding it from MODE_CREATE removes it from the create request body documentation — the server generates it.
2. Wire the five controllers
Each controller is a thin subclass. You implementgetResourceClass(), buildRoute(), and __invoke().
Create
View
Update
Delete
List
What the framework handles for you
- 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()hidesanimal_uuidfrom the create body andweightfrom list responses; the rest of the endpoints still see both. - OpenAPI — all five operations are generated from the single resource. Add a field to
AnimalResource::init()and every operation updates at once.
Nested resources
BecausebuildRoute() is fully explicit, nested URLs require no special setup — add more path segments and declare each one via ->pathProperty():
Optional: IDE autocomplete via the DocBlock generator
Run the docblock generator once. See Generate OpenAPI and docblocks for the script. It produces:@propertyannotations onAnimalResource— so$animal->name,$animal->statusetc. autocomplete.- A typed request class per controller that has path params, sorting, filtering, or pagination:
AnimalViewRequest/AnimalDeleteRequest— typedpath()AnimalUpdateRequest— typedpath()AnimalListRequest— typedsorting(),filtering(),paginator()
@param annotation on __invoke with the generated class: