Symfony Forms reference
In a nutshell
When used in Symfony applications, the symfony/forms
package makes it easier to work with forms in web applications. More specifically it can:
- Convert submitted form data into PHP objects (usually Doctrine entities) and vice-versa.
- Validate submitted data using validator constraints that are usually defined on Doctrine entities.
- Generate the HTML mark up using information defined in the Form Type class (see below).
- Display error messages when submission is invalid.
- Generate a hidden _token field to protect against CSRF attacks.
The forms workflow
When working with forms in Symfony, you usually take the following approach:
- Build the form in a controller or in a dedicated form class.
- Render the form in a template.
- Process the form in a controller to validate the submitted data, transform it into PHP data, and do something with it (e.g., persist it to a database).
Build a Form Type
symfony console make:form CommentFormType Comment
This will generate src/Form/CommentFormType.php
that looks like this:
<?php
namespace App\Form;
use App\Entity\Comment;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CommentFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('author')
->add('text')
->add('email')
->add('createdAt')
->add('photoFilename')
->add('conference')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Comment::class,
]);
}
}
A form type is a class that describes form fields bound to an entity. Symfony converts between the submitted data and the entity class properties. It uses metadata from the corresponding entity (e.g., Doctrine metadata) to guess the configuration for each field. For example, it’ll render a text
property as a textarea
.
Display a form
1. Create the form in a controller action and pass it to the template
<?php
namespace App\Controller;
use App\Entity\Comment;
use App\Entity\Conference;
use App\Form\CommentFormType;
use App\Repository\CommentRepository;
use App\Repository\ConferenceRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ConferenceController extends AbstractController
{
#[Route("/conference/{slug}", name: 'conference')]
public function show(Request $request, Conference $conference): Response
{
$comment = new Comment();
$form = $this->createForm(CommentFormType::class, $comment);
return $this->render('conference/show.html.twig', [
'conference' => $conference,
'comment_form' => $form->createView()
]);
}
}
2. Render form in twig
<h2>Add your own feedback</h2>
{{ form(comment_form) }}
This should render something like:
Customise a form
You can customize the buildForm
method to add, remove, or modify fields:
<?php
namespace App\Form;
use App\Entity\Comment;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Image;
class CommentFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('author', null, ['label' => 'You name'])
->add('text')
->add('email')
->add('createdAt')
->add('photo', FileType::class, [
'required' => false,
'mapped' => false,
'constraints' => [
new Image(['maxSize' => '1024k'])
]
])
->add('conference')
->add('submit', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Comment::class,
]);
}
}
Validate form submission
1. Add validation constraints
Since most forms will be bound to a Doctrine entity, you’ll typically add validation constraints to your entities. For example:
<?php
namespace App\Entity;
use App\Repository\CommentRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: CommentRepository::class)]
class Comment
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\NotBlank] // validation constraint
private $author;
#[ORM\Column(type: 'text')]
#[Assert\NotBlank] // validation constraint
private $text;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\NotBlank] // validation constraint
#[Assert\Email] // validation constraint
private $email;
// code omitted for brevity
}
4. Check if form is valid in controller
<?php
namespace App\Controller;
// Imports
class ConferenceController extends AbstractController
{
// code omitted for brevity
#[Route("/conference/{slug}", name: 'conference')]
public function show(Request $request, Conference $conference): Response
{
$comment = new Comment();
$form = $this->createForm(CommentFormType::class, $comment);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$comment->setConference($conference);
$this->entityManager->persist($comment);
$this->entityManager->flush();
return $this->redirectToRoute('conference', ['slug' => $conference->getSlug()]);
}
// render some template...
}
}
Now, when the form is submitted with invalid data, the Twig form()
method will show any validation errors:
Debug forms using the Symfony Profiler
Click on the Form panel:
You can view the validator calls:
Or view the submitted data and any errors.
Sources
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment