HTTP Controller Paramateres
This feature only works in HTTP Controllers. It doesn't work with pure Responders.
Controllers allow to validate and map incoming HTTP data into reusable objects.
Usage
Attributes
You don't have to call the validator manually if you use Controllers. You can use parameter attributes instead.
For example, if a MyValidator exists that returns MyValidatedData model,
you can add #[ValidatedRequest( annotation to the
parameter of the MyValidatedData. A controller is going to validate the
incoming POST data using the MyValidator, and in case of success, it's
going to inject the data model into the parameter:
php// ... public function createResponse( #[ValidatedRequest(MyValidator::class)] MyValidatedData $data, ) { // ... } // ...
Error Handling
To handle errors, you can create an optional method marked in the
#[OnParameterResolution] attribute. If such a method exists, then will be
be called in case of validation failure.
If no such method exists, the controller is going to return a generic
400 Bad Request response.
handle method's arguments are forwarded into the error validation method.
It can only use the parameters that are already resolved in the handle method
plus an extra argument with validation errors and request/response pair.
Adding new arguments to the error handler besides those is going to cause an error.
php<?php namespace App\HttpResponder; use App\HttpRouteSymbol; use App\InputValidatedData\BlogPostForm; use App\InputValidator\BlogPostFormValidator; use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\Attribute\OnParameterResolution; use Distantmagic\Resonance\Attribute\ValidatedRequest; use Distantmagic\Resonance\HttpControllerParameterResolution; use Distantmagic\Resonance\HttpControllerParameterResolutionStatus; use Distantmagic\Resonance\HttpResponder\HttpController; use Distantmagic\Resonance\HttpResponderInterface; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\SingletonCollection; use Ds\Map; use Ds\Set; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::POST, pattern: '/blog_post/create', routeSymbol: HttpRouteSymbol::BlogPostCreate, )] #[Singleton(collection: SingletonCollection::HttpResponder)] final readonly class BlogPostStore extends HttpController { public function createResponse( #[ValidatedRequest(BlogPostFormValidator::class)] #[OnParameterResolution( status: HttpControllerParameterResolutionStatus::ValidationErrors, forwardTo: 'handleValidationErrors', )] BlogPostForm $blogPostForm, ): HttpResponderInterface { /* inser blog post, redirect, etc */ /* ... */ } /** * @param Map<string,Set<string>> $errors */ public function handleValidationErrors( ServerRequestInterface $request, ResponseInterface $response, HttpControllerParameterResolution $resolution, ): HttpResponderInterface { $response = $response->withStatus(400); /* render form with errors */ /* ... */ } }