pln0w/rest-api-validator

This package is abandoned and no longer maintained. No replacement package was suggested.

A package for creating request objects for pre-controller validation

1.0.0 2019-12-18 15:28 UTC

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 }