Forms

Symfony's Form component gives you a structured way to build, render, and process HTML forms that are tied directly to a PHP object — very often a Doctrine Entity, like the Article class from the Doctrine ORM page. Instead of hand-writing form fields and manually pulling values out of $_POST, you describe the form's fields once in a reusable class, and Symfony takes care of rendering, populating, and reading it back.

Defining a FormType

A form's fields are defined in a dedicated class that extends AbstractType. Its buildForm() method adds one field at a time, each tied to a property on the object the form represents:

<?php
namespace App\Form;

use App\Entity\Article;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ArticleType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('title', TextType::class)
            ->add('content', TextareaType::class);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Article::class,
        ]);
    }
}

configureOptions() sets data_class to Article::class, telling Symfony which entity this form is bound to — that's what lets the form read the entity's current values when displaying it, and write submitted values back onto a new or existing Article object.

Using the Form in a Controller

Inside a controller, you build the form for a given Article, let Symfony pull the submitted data out of the request, and check whether it was actually submitted and valid:

<?php
$article = new Article();
$form = $this->createForm(ArticleType::class, $article);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
    $entityManager->persist($article);
    $entityManager->flush();

    return $this->redirectToRoute('article_show', ['id' => $article->getId()]);
}

return $this->render('article/new.html.twig', ['form' => $form->createView()]);

createForm() builds the form bound to a fresh (empty) $article. handleRequest() checks whether the request contains submitted form data and, if so, maps it onto $article's properties. isSubmitted() and isValid() together confirm the request was a real submission and that it passed all validation checks before you save anything — the same persist() / flush() pair from the Doctrine ORM page handles the actual save.

Rendering the Form in Twig

In the simple case, rendering the whole form — every field, label, and error message — takes a single Twig function call:

{{ form(form) }}

That's enough to get a working, submittable form on the page. Symfony also lets you render a form field by field for full control over the surrounding markup, but {{ form(form) }} is the fastest way to get something working.

Note: isValid() only returns true once the submitted data satisfies the entity's validation constraints — annotations or attributes that declare rules like "required" or "maximum length". That's exactly what the next page covers.
Next steps: Head to Validation to learn how to define the constraints that isValid() checks against.