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 */ /* ... */ } }