Symfony form builder
last modified July 5, 2020
Symfony form builder tutorial shows how to create HTML forms with form builders in Symfony. To create forms without form builders, look at Symfony form tutorial.
Symfony
Symfony is a set of reusable PHP components and a PHP framework for web projects. Symfony was published as free software in 2005. Symfony was heavily inspired by the Spring Framework.
HTML form
HTML forms are used for interaction between a user and a web site or application. They allow users to send data to the web site. An HTML Form is made of one or more widgets. Those widgets can be text fields, select boxes, buttons, checkboxes, or radio buttons. The widgets are often paired with a label that describes their purpose.
Symfony Form component
The Symfony Form component allows us to create, process and reuse HTML forms.
Symfony documentation uses the term form type to refer to single form fields
(e.g. <input type="text">
), groups of single form fields, and
the entire <form>
tag. There are predefined form types such
as PasswordType
, MoneyType
, or TextType
;
developers can create their own form types as well.
Symfony form builder example
In the following example, we create an HTML form with a Symfony form builder. The data from the form is processed by a Symfony controller.
$ symfony new myform
With symfony
CLI, we create a new Symfony skeleton project.
$ cd myform
We go to the project directory.
$ composer req annot twig form symfony/validator symfony/security-csrf
We install the following packages: annotations
, twig
,
form
, symfony/validator
, and symfony/security-csrf
.
<?php namespace App\Form; use Symfony\Component\Validator\Constraints as Assert; class Note { /** * @Assert\NotBlank */ public ?string $message = ''; /** * @Assert\NotBlank * @Assert\Type("\DateTime") */ public ?\DateTime $created = null; public function __construct() { $this->created = new \DateTime(); } }
The Note consists of two attributes: message string and created datetime. The created datetime is going to be filled with the current datetime.
/** * @Assert\NotBlank */ public ?string $message = '';
The NotBlank
assertion ensures that the message must not be blank.
<?php namespace App\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class NoteFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('message', TextType::class, ['help' => 'Enter your Message']) ->add('created', DateTimeType::class, ['widget' => 'single_text']) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'csrf_field_name' => '_token', ]); } }
We define the NoteFormType
. It consists of two built-in types:
TextType
, and DateTimeType
.
$builder ->add('message', TextType::class, ['help' => 'Enter your Message']) ->add('created', DateTimeType::class, ['widget' => 'single_text']) ;
With the form builder, we add two built-in form types to the note form type. Each
subtype can be customized with various options, such as help
or
single_text
.
public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'csrf_field_name' => '_token', ]); }
Furthermore, we can customize the note form type in the configureOptions
function. By default, the form builder sets up the CSFR protection. For instance,
with the csrf_field_name
, we can customize the name of the CSRF field used.
<?php namespace App\Controller; use App\Form\Note; use App\Form\NoteFormType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class NoteController extends AbstractController { /** * @Route("/note", name="note") * @param Request $request * @return Response */ public function index(Request $request): Response { $note = new Note(); $noteForm = $this->createForm(NoteFormType::class, $note); $noteForm->handleRequest($request); if ($noteForm->isSubmitted() && $noteForm->isValid()) { $data = $noteForm->getData(); $message = $data->message; $created = $data->created->format('Y-m-d h:i:s'); return $this->redirectToRoute('success', ['message' => $message, 'created' => $created]); } return $this->render('note/index.html.twig', [ 'note_form' => $noteForm->createView() ]); } }
Following the Symfony best practices, the controller both displays the form and processes the form.
$note = new Note(); $noteForm = $this->createForm(NoteFormType::class, $note);
The form is created with the createForm
function. It is passed the
form type as the first parameter.
$noteForm->handleRequest($request);
The handleRequest
function checks if the form submitted any data.
If not, the data is loaded from the request and validated. The form is marked to
be submitted.
if ($noteForm->isSubmitted() && $noteForm->isValid()) {
We check if the form has been submitted and if the data passed the validation.
$data = $noteForm->getData(); $message = $data->message; $created = $data->created->format('Y-m-d h:i:s'); return $this->redirectToRoute('success', ['message' => $message, 'created' => $created]);
We retrieve the data and redirect to the success
route.
return $this->render('note/index.html.twig', [ 'note_form' => $noteForm->createView() ]);
The render
function either generates the initial form or the
form with possible errors.
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class SuccessController extends AbstractController { /** * @Route("/success", name="success") * @param Request $request * @return Response */ public function index(Request $request): Response { $message = $request->query->get("message"); $created = $request->query->get("created"); return $this->render('success/index.html.twig', ['message' => $message, 'created' => $created]); } }
The SuccessController
sends the data to the appropriate Twig view.
{% form_theme note_form 'bootstrap_4_layout.html.twig' %} {% extends 'base.html.twig' %} {% block title %}Note form{% endblock %} {% block body %} <div class="container"> {{ form_start(note_form) }} {{ form_widget(note_form) }} <input type="submit" value="Submit" class="btn btn-success"> {{ form_end(note_form) }} </div> {% endblock %}
This Twig template file contains the form. The form is rendered with the
form_start
, form_widget
, and form_end
directives. Theming is applied with the form_theme
directive.
{% form_theme note_form 'bootstrap_4_layout.html.twig' %}
Form themes can be applied globally via configuration or locally with the
form_theme
directive. Here we use the built-in Bootstrap 4 theme.
The first argument of the form_theme tag (note_form
in this
example) is the name of the variable that stores the form view object.
The name is derived from the provided form type. The second argument is the path
to the Twig template that defines the form theme.
{% extends 'base.html.twig' %} {% block title %}Success{% endblock %} {% block body %} <p> Form successfully submitted. </p> <p> {{ message }} at {{ created }} </p> {% endblock %}
This is the view to display the submitted data.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{% block title %}Welcome!{% endblock %}</title> {% block stylesheets %} <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> {% endblock %} </head> <body> {% block body %}{% endblock %} {% block javascripts %}{% endblock %} </body> </html>
The base.html.twig
template contains code that is shared
by other template files. It contains the Bootstrap 4 styling.
$ symfony serve
We run the application and navigate to localhost:8000/note
.
In this tutorial we have generated a form with Symfony form builder.
List all Symfony tutorials.