Home > Software design >  How to pass request to DTO for assert validation?
How to pass request to DTO for assert validation?

Time:05-11

I am trying to implement symfony validation asset to the request.

I am passing form-data from the postman to the route in controller.

#[Route(path: '/test', name: 'test', methods: 'GET')]
    public function login(LoginRequest $loginRequest): Response

I have created a loginRequest DTO as following:

class LoginRequest
{
    public function __construct(
        /**
         * @Assert\NotBlank
         */
        public string $username,
        /**
         * @Assert\NotBlank
         */
        public string $password
    ) {
    }
}

But I am getting following error.

Cannot autowire service "App\Dto\LoginRequest": argument "$username" of method "__construct()" is type-hinted "string", you should configure its value explicitly.

Can anybody help me how can I use DTO for validation to params request ?

CodePudding user response:

You need to use the Serializer component in your method and deserialize your DTO to create an object with your data. Create a request with header Content-Type: application/json and send data in json format, not form-data

Your DTO should be declared like this:

use Symfony\Component\Validator\Constraints as Assert;

class LoginRequest
{
    /**
     * @Assert\NotBlank()
     */
    public string $username;

    /**
     * @Assert\NotBlank()
     */
   public string $password; 
   
}

Controller method:

    use Symfony\Component\Serializer\SerializerInterface;


    #[Route(path: '/test', name: 'test', methods: 'GET')]
    public function login(Request  $request, SerializerInterface  $serializer, ValidatorInterface $validator): Response
    { 
        $dto = $serializer->deserialize($request->getContent(), LoginRequest::class, 'json');
        $errors = $validator->validate($dto);
        if (count($errors) > 0) {
            throw new BadRequestHttpException((string) $errors);
        }

        // ...
    }

CodePudding user response:

It's because your application tries to create a service with your DTO and autowire it's contructor arguments.

The defaut service container configuration is the following

# config/services.yaml
services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Tests,Kernel.php}'

    # ...

To exclude your DTO from your service container you could create it in a folder named Dto and add this folder to the exclude line of the configuration file like this.

exclude: '../src/{DependencyInjection,Entity,Tests,Dto,Kernel.php}'

  • Related