Skip to content

RequestInputBundle converts request data into DTO inputs objects with validation.

License

Notifications You must be signed in to change notification settings

sfmok/request-input-bundle

Repository files navigation

RequestInputBundle

CI codecov Latest Stable Version License

RequestInputBundle converts request data into DTO inputs objects with validation.

  • Request data supported: json, xml and form based on Content-Type header.
  • Resolve inputs arguments for controllers actions.
  • Create DTO inputs outside controllers
  • Validate DTO inputs objects.
  • Global YAML configuration.
  • Custom Configuration via Input Attribute per controller action.

Installation

Require the bundle with composer:

composer require sfmok/request-input-bundle

How to use

  • Create DTO input and implements Sfmok\RequestInput\InputInterface
use Sfmok\RequestInput\InputInterface;

class PostInput implements InputInterface
{
    #[Assert\NotBlank]
    private string $title;

    #[Assert\NotBlank]
    private string $content;

    #[Assert\NotBlank]
    private array $tags;

    #[SerializedName('author')]
    #[Assert\NotBlank]
    private string $name;
    
    # getters and setters or make properties public
}
  • Use DTO input in your controller action as an argument:
class PostController
{
    # Example with global config
    #[Route(path: '/posts', name: 'create')]
    public function create(PostInput $input): Response
    {
        dd($input);
    }
    
    # Example with specific config
    #[Route(path: '/posts', name: 'create')]
    #[Input(format: 'json', groups: ['create'], context: ['groups' => ['create']])]
    public function create(PostInput $input): Response
    {
        dd($input);
    }
}

Validations

  • Response header
Content-Type: application/json; charset=utf-8
  • Response body
{
  "type": "https://symfony.com/errors/validation",
  "title": "Validation Failed",
  "detail": "title: This value should not be blank.",
  "violations": [
    {
      "propertyPath": "title",
      "title": "This value should not be blank.",
      "parameters": {
        "{{ value }}": "\"\""
      },
      "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
    }
  ]
}

Deserialization

Whether the request data contains invalid syntax or invalid attributes types a clear 400 json response will return:

  • Data Error
{
  "title": 12
}
{
  "title": "Deserialization Failed",
  "detail": "Data error",
  "violations": [
    {
      "propertyPath": "title",
      "message": "This value should be of type string",
      "currentType": "int"
    }
  ]
}
  • Syntax error:
{
  "title": "foo",
}
{
  "title": "Deserialization Failed",
  "detail": "Syntax error",
  "violations": []
}

Configuration

# config/packages/request_input.yaml
request_input:
  enabled: true # default value true
  formats: ['json'] # default value ['json', 'xml', 'form']
  skip_validation: true # default value false

You can also override the format using attribute input and specify the format explicitly.

Create DTO input outside controller

You just need to inject InputFactoryInterface e.g:

<?php

declare(strict_types=1);

namespace App\Manager;

use App\Dto\PostInput;
use Sfmok\RequestInput\InputInterface;
use Symfony\Component\HttpFoundation\Request;
use Sfmok\RequestInput\Factory\InputFactoryInterface;

class PostManager
{
    public function __construct(private InputFactoryInterface $inputFactory)
    {
    }

    public function getInput(Request $request): InputInterface
    {
        return $this->inputFactory->createFromRequest($request, PostInput::class);
    }
}

License

The MIT License (MIT). Please see License File for more information.