The code-snippets in this article are obtained from: https://symfony.com/doc/current/forms.html
1) Installation
composer require symfony/form
2) Building form in controller
<?php
// src/Entity/Task.php
namespace App\Entity;
class Task
{
protected $task;
protected $dueDate;
public function getTask()
{
return $this->task;
}
public function setTask($task)
{
$this->task = $task;
}
public function getDueDate()
{
return $this->dueDate;
}
public function setDueDate(\DateTime $dueDate = null)
{
$this->dueDate = $dueDate;
}
}
<?php
// src/Controller/DefaultController.php
namespace App\Controller;
use App\Entity\Task;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class DefaultController extends Controller
{
public function new(Request $request)
{
// creates a task and gives it some dummy data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, array('label' => 'Create Task'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$task = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
// $entityManager = $this->getDoctrine()->getManager();
// $entityManager->persist($task);
// $entityManager->flush();
return $this->redirectToRoute('task_success');
}
return $this->render('default/new.html.twig', array('form' => $form->createView(),));
}
}
{# templates/default/new.html.twig #}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
{#
form_start - renders the start tag of the form, with enctype
form_widget - fields, validation errors
form_end - eng tag of the form + automatic CSRF protection
#}
<!-- templates/default/new.html.php -->
<?php echo $view['form']->start($form) ?>
<?php echo $view['form']->widget($form) ?>
<?php echo $view['form']->end($form) ?>
{% endraw %}
3) Validation
composer require symfony/validator
Annotation is used for validation
<?php
// src/Entity/Task.php
namespace App\Entity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class Task
* @property string $task
* @property \DateTime $dueDate
* @package App\Entity
*/
class Task
{
/**
* @Assert\NotBlank()
*/
protected $task;
/**
* @Assert\NotBlank()
* @Assert\Type("\DateTime")
*/
protected $dueDate;
/**
* @return string
*/
public function getTask(): string
{
return $this->task;
}
/**
* @param string $task
*/
public function setTask($task): void
{
$this->task = $task;
}
/**
* @return \DateTime
*/
public function getDueDate(): \DateTime
{
return $this->dueDate;
}
/**
* @param \DateTime $dueDate
*/
public function setDueDate(\DateTime $dueDate): void
{
$this->dueDate = $dueDate;
}
}
{# templates/default/new.html.twig #}
{{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
https://symfony.com/doc/current/reference/forms/types.html
Passing options to Fields
->add('dueDate', DateType::class, array(
'widget' => 'single_text',
'required' => true // applies client-side validation if enabled,
'label' => 'Due Date',
))
->add('task', null, array('attr' => array('maxlength' => 4)))
Creating Form Class
<?php
// src/Form/TaskType.php
namespace App\Form;
use App\Entity\Task;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task')
->add('dueDate', null, ['widget' => 'single_text'])
->add('agreeTerms', CheckboxType::class, ['mapped' => false])
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
// indicates the type of class which holds data
$resolver->setDefaults([
'data_class' => Task::class
]);
}
}
<?php
// src/Controller/TaskController.php
namespace App\Controller;
use App\Form\TaskType;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Task;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
class TaskController extends Controller
{
/**
* @Route("/task/new2")
*/
public function newFromFormClass(Request $request)
{
$task = new Task();
$task->setTask("Here is the new task");
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createForm(TaskType::class, $task);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$task = $form->getData();
echo $form->get('agreeTerms')->getData();
return $this->redirectToRoute('task_success');
}
return $this->render('task/new.html.twig', [
'form' => $form->createView()
]);
}
}