symfonysymfony5

How to pass request to DTO for assert validation?


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 ?


Solution

  • 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);
            }
    
            // ...
        }