Forms
Forms are defined in their own class, so you can reuse them anywhere. Add fields and Symfony renders the right HTML input for each type (emails, passwords, dates, files, etc.)
In the controller, create the object that will hold the data and pass it to createForm(). Then, handleRequest() does the heavy lifting: it detects whether the form was submitted and fills $signup with the request data.
If the submitted data is valid, process it and redirect, so reloading the page never resubmits the form. If it's not valid, the form is displayed again with the errors next to each field. The next lesson shows where those validation rules come from.
Rendering the form in Twig takes a single form() call: it outputs the fields, their labels, the validation errors and a hidden token that protects you against CSRF attacks.
<?phpnamespace App\Form;use Symfony\Component\Form\AbstractType;use Symfony\Component\Form\Extension\Core\Type\EmailType;use Symfony\Component\Form\Extension\Core\Type\PasswordType;use Symfony\Component\Form\FormBuilderInterface;class SignupType extends AbstractType{ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('email', EmailType::class) ->add('password', PasswordType::class); }}<?phpnamespace App\Controller;use App\Dto\SignupRequest;use App\Form\SignupType;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Attribute\Route;class SignupController extends AbstractController{ #[Route('/signup', methods: ['GET', 'POST'])] public function signup(Request $request): Response { $signup = new SignupRequest(); $form = $this->createForm(SignupType::class, $signup); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // $signup now contains the submitted data // ... do something with it (save it, send an email, ...) return $this->redirectToRoute('signup_success'); } return $this->render('signup.html.twig', [ 'signup_form' => $form, ]); }}{% extends 'base.html.twig' %}{% block title %}Sign up{% endblock %}{% block body %} <h1>Create your account</h1> {{ form(signup_form) }}{% endblock %}