Back to symfony.com

Lesson 9 of 11 · 4 min

Click any paragraph or press to highlight its code

Forms & validation

Validation rules are declared where your data lives, as attributes. Symfony ships with dozens of constraints: emails, URLs, ranges, IBANs, image dimensions... and you can create your own.

Now the fun part: #[MapRequestPayload] takes the JSON body of the request, deserializes it into your object and validates it. One attribute replaces all that boilerplate.

If validation fails, Symfony automatically returns a 422 response detailing every error. If it succeeds, your controller receives a perfectly typed object.

Building HTML forms instead of APIs? The Symfony Form component renders, processes and validates them reusing these same constraints, including protection against CSRF attacks.

<?phpnamespace App\Dto;use Symfony\Component\Validator\Constraints as Assert;class SignupRequest{    public function __construct(        #[Assert\NotBlank]        #[Assert\Email]        public string $email,        #[Assert\Length(min: 8)]        public string $password,    ) {    }}
<?phpnamespace App\Controller;use App\Dto\SignupRequest;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;use Symfony\Component\Routing\Attribute\Route;class SignupController extends AbstractController{    #[Route('/api/signup', methods: ['POST'])]    public function signup(        #[MapRequestPayload] SignupRequest $request,    ): JsonResponse {        // if you get here, the JSON payload was valid; otherwise,        // Symfony already returned a 422 response with the errors        return $this->json(['welcome' => $request->email]);    }}