pln0w / rest-api-validator
A package for creating request objects for pre-controller validation
Requires
- php: ^7.4
- symfony/dependency-injection: 5.0.*
- symfony/http-foundation: 5.0.*
- symfony/http-kernel: 5.0.*
- symfony/validator: 5.0.*
This package is auto-updated.
Last update: 2022-08-18 21:40:51 UTC
README
A simple library to force and make consistent development REST API controllers. It allows to define structure of the payload and it validator constraints. It also provides much easier way to access validated data from within the controller body.
Installation
composer require pln0w/rest-api-validator
Add following section to your services.yml
Pawly\RestApiValidator\Resolver\CustomRequestResolver: arguments: - '@validator' tags: - { name: controller.request_value_resolver }
Each request object must have request_stack service injected, i.e:
User\Infrastructure\Request\RegisterUserRequest: arguments: - '@request_stack'
Usage
-
Steps to provide validation to your controllers:
- Create custom request overriding Pawly\RestApiValidator\Request\AbstractCustomRequest
- Define request class properties that you want to map request values with
- Add validation constraints to $metadata (no yaml, no addnotations - pure PHP config)
- (optional) Override getters for properties in needed or add constraint explicit against getter
See validation docs: https://symfony.com/doc/master/validation.html
Example 1.
<?php declare(strict_types=1); namespace User\Infrastructure\Request; use Pawly\RestApiValidator\Request\AbstractCustomRequest; use Symfony\Component\Validator\Constraints as Assert; class RegisterUserRequest extends AbstractCustomRequest { protected ?string $email = null; protected ?string $password = null; /** * @inheritDoc */ public function getValidationRules() { return new Assert\Collection([ 'email' => new Assert\Email(), 'password' => [ new Assert\NotBlank(), new Assert\Length(['min' => 6]) ] ]); } }
- Create controller having this request injected
<?php declare(strict_types=1); namespace User\Infrastructure\Controller; use Pawly\RestApiValidator\Response\ApiResponse; use User\Infrastructure\Request\RegisterUserRequest; final class RegisterUserAction { public function __invoke(RegisterUserRequest $request): ApiResponse { // do some stuff ... $email = $request->getEmail(); return ApiResponse::json(['email' => $email], ApiResponse::HTTP_OK); } }
Different custom request validation example
<?php declare(strict_types=1); namespace User\Infrastructure\Request; use Pawly\RestApiValidator\Request\AbstractCustomRequest; use Symfony\Component\Validator\Constraints as Assert; use Shared\Domain\ValueObject\Email; class RegisterUserRequest extends AbstractCustomRequest { protected ?string $email = null; protected ?string $password = null; /** * @inheritDoc */ public function getValidationRules() { return new Assert\Collection([ 'email' => new Assert\Email(), 'password' => [ new Assert\NotBlank(), new Assert\Length(['min' => 6]) ] ]); } public function getEmail(): Email { return new Email($this->email); } }
-
Validation errors handling
If request has invalid data, then exception is thrown and handled in subscriber, that will provide following message structure:
{ "status": 422, "message": "Request validation error", "details": { "email": "This value should not be correct email address.", "password": "This value should not be blank." } }
More
Validate responses interface
If you want to ensure you use unified response for controllers, you can enable checking response interface by addint below definition to your services.yaml
Pawly\RestApiValidator\Subscriber\ValidateResponseInterfaceSubscriber: tags: - { name: kernel.event_subscriber, event: kernel.response }