Nella lezione precedente abbiamo creato un form direttamente all’interno del controller, utilizzando lo schema:


class DefaultController extends Controller // estende la classe Controller di Symfony
{
	...
    
    public function newAction(Request $request)
   {
       ...

       // 1. creo i contenuti HTML del form
       $form = $this->createFormBuilder($task)

       ....

Il metodo ‘createFormBuilder()’ è utilizzato all’interno di ‘class DefaultController extends Controller’

Form come classe

Creare un form in una classe separata ci permette di riutilizzarlo più facilmente, lo schema di funzionanmento sarà

Il nostro controller invoca la classe contenente le istruzioni per creare il form: $form = $this->createForm(TaskType::class, $task);


public function newAction(Request $request)
   {
        ...

       // 1. creo i contenuti HTML del form
       // invia $task a TaskType.php classe TaskType
       $form = $this->createForm(TaskType::class, $task);

        ...

La Classe per creare il form TaskType.php:


...

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task')
            ->add('dueDate', null, array('widget' => 'single_text'))
            ->add('save', SubmitType::class)
...

Il codice completo

src/AppBundle/Controller/DefaultController.php


<?php

// src/AppBundle/Controller/DefaultController.php
namespace AppBundle\Controller;

use AppBundle\Entity\Task; // carica Task.php creato da me
use AppBundle\Form\TaskType; // carica TaskType.php creato da me

use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html render()

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route

use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfony per usare createForm()

class DefaultController extends Controller // deve estendere Controller
{
	/**
	* @Route("/form")
	*/
    
    public function newAction(Request $request)
   {
       // creo il nuovo oggetto 
       $task = new Task();
       // die("interrompi qui"); // debug

       // 1. creo i contenuti HTML del form
       // invia $task a TaskType.php classe TaskType
       $form = $this->createForm(TaskType::class, $task);
       
       // 3. riconosce che il form non è stato inviato e non fa nulla
       $form->handleRequest($request); 
       
       // 4. se il form è inviato AND valido
       if ($form->isSubmitted() && $form->isValid()) {
           // $form->getData() holds the submitted values
           // but, the original `$task` variable has also been updated
           $task = $form->getData();// ottieni i dati dal form

           // die ("interrompi qui 2");
           // ... perform some action, such as saving the task to the database
           // for example, if Task is a Doctrine entity, save it!
           // $em = $this->getDoctrine()->getManager();
           // $em->persist($task);
           // $em->flush();

           // alla fine fai redirect all'esterno 
           return $this->redirect('http://www.lucedigitale.com');
           
           // oppure verso una @Route di Symfony
           //return $this->redirectToRoute('homepage');
       }

       // 2. Il form viene creato e renderizzato
       return $this->render('default/new.html.twig', array(
           'form' => $form->createView(),
       ));
   }
}

src/AppBundle/Form/TaskType.php


<?php

// src/AppBundle/Form/TaskType.php
namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType; // form astratto
use Symfony\Component\Form\FormBuilderInterface; // buildForm()
use Symfony\Component\Form\Extension\Core\Type\SubmitType; // SubmitType::class

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task')
            ->add('dueDate', null, array('widget' => 'single_text'))
            ->add('save', SubmitType::class)
        ;
    }
}

src/AppBundle/Entity/Task.php


<?php

// src/AppBundle/Entity/Task.php
namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert; // serve per @Assert\...

class Task // dichiarazione esplicita dell'oggetto
{
    
    /**
     * @Assert\NotBlank()
     * @Assert\EqualTo("Andrea")
     */
    public $task;    // cose da fare
    
     /**
     * @Assert\NotBlank()
     * @Assert\Type("\DateTime")
     */
    protected $dueDate; // scadenza

    
    // NB metodi get e set obbligatori per permettere a 'Form component' di symfony di funzionare correttamente
    public function getTask() // ottieni le cose da fare
    {
        return $this->task; // assegna il valore che proviene dall'istanza $this->
    }

    public function setTask($task) // setta le cose gda fare
    {
        $this->task = $task;
    }

    public function getDueDate() // ottieni la scadenza
    {
        return $this->dueDate;
    }

    public function setDueDate(\DateTime $dueDate = null) // setta la scadenza
    {
        $this->dueDate = $dueDate;
    }
}

app/Resources/views/default/new.html.twig


{# app/Resources/views/default/new.html.twig #}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}

Come funziona?

0. al primo caricamento viene creato l’oggetto che contiene le mie variabili
$task = new Task();

1.
vengono creati i tag HTML per il form
$form = $this->createForm(TaskType::class, $task); -> punta alla Classe TaskType.php

Viene renderizzato il form render(‘default/new.html.twig’…

2. il metodo $form->handleRequest($request); rileva che il form non è stato inviato e non fa nulla

3. quando premo ‘submit’
– $form->handleRequest($request); ritorna TRUE
– i dati vengono salvati in $form e aggiornati in $task

a)
– $form viene controllato
– se non sono validi && $form->isValid()) { -> in realtà è una scorciatoia che significa $task->isValid())
– viene automaticamente renderizzata di nuovo la pagina con gli errori di validazione

b)
– $form viene controllato
– se sono validi && $form->isValid()) {
– viene inviata la richiesta POST alla pagina di provenieneza
– interrompe lo script con return facendo un redirect ad un’altra pagina, ad esempio di ringraziamento

NB: il redirect non darà la possibilità all’utente di fare “Refresh nel browser ed inviare di nuovo il form

Bibliografia:
symfony.com/doc/current/forms.html – Creating Form Classes