Il Form component per Symfony è un componente standalone che può essere utilizzato anche al di fuori di Symfony.

In questa lezione creeremo un form direttamente all’interno di un Controller:


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 con Dummy Data

1. Creare in src/AppBundle/Entity/Task.php


<?php

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

class Task // dichiarazione esplicita dell'oggetto
{
    // proprietà o variabili non accessibile dall'esterno della classe
    protected $task;    // cose da fare
    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;
    }
}

2. Creare in 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 Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html
use Symfony\Component\Form\Extension\Core\Type\TextType; // form di Symfony
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

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

class DefaultController extends Controller // estende la classe Controller di Symfony
{
	/**
	* @Route("/form")
	*/
    public function newAction(Request $request) // metodo
    {
        // Utilizzo della classe Task di Task.php per creare l'oggetto $task INIZIO -> crea $task
        $task = new Task();// creo un oggetto istanziando la classe Task
        $task->setTask('Write a blog post'); // assegno $task, le cose da fare
        $task->setDueDate(new \DateTime('tomorrow')); // setta la scadenza
        // Utilizzo della classe Task di Task.php per creare l'oggetto $task FINE

        // Creazione del form utilizzando le classi di Symfony INIZIO -> crea $form
        $form = $this->createFormBuilder($task)// invia al metodo createFormBuilder l'oggetto $task con tutte i dati
            // istruzioni per creare i TAG HTML INIZIO
            ->add('task', TextType::class)// invia al metodo add() assegnando la propietà 'task' di Task.php e la variabile statica 'TextType::class' che indica un campo di testo
            ->add('dueDate', DateType::class)// come sopra
            ->add('save', SubmitType::class, array('label' => 'Create Post'))// come sopra con aggiunta della label
            // istruzioni per creare i TAG HTML FINE
            ->getForm(); // questo metodo di Symfony restituisce il form
        // Creazione del form utilizzando le classi di Symfony FINE

        // ivia l'istruzione al template .twig inviando $form
        // la risposta finale è invio al metodo render() - template.twig - form - $form
        return $this->render('default/new.html.twig', array(
            'form' => $form->createView(),
        ));
    }
}

2. Creare in app/Resources/views/default/new.html.twig


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

Puntare il browser su: http://localhost/symfonytest/first_test_symfony/web/form

Come funziona?
Si avvia DefaultController.php:
1. Crea l’oggetto $task instanziando in Task.php la class Task
2. Crea l’oggetto $form con il metodo createFormBuilder() di Symfony
3. Renderizza il form inviandolo al template ,twig con il metodo render() di Symfony

NB: – $task = new Task(); – sono dummy data – dati di esempio!!!

Form senza Dummy Data

Ripuliamo dai dati generati come esempio matenendo solo il form


<?php

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

use AppBundle\Entity\Task; // carica Task.php creato da me
use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html
use Symfony\Component\Form\Extension\Core\Type\TextType; // form di Symfony
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

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

class DefaultController extends Controller // estende la classe Controller di Symfony
{
	/**
	* @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
       $form = $this->createFormBuilder($task)
           ->add('task', TextType::class) // il nome delle varibili è lo stesso di Task.php
           ->add('dueDate', DateType::class)
           ->add('save', SubmitType::class, array('label' => 'Create Task'))
           ->getForm();
       
       // 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(),
       ));
   }
}

Puntare il browser su: http://localhost/symfonytest/first_test_symfony/web/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->createFormBuilder($task)

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()) {
– 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

Validazione

Come visto sopra $form->isValid() è una scorciatoia per scrivere $task->isValid()
Il controllo di validazione quindi verrà effettuato su direttamente sull’oggetto e non sul form come si fa di solito in HTML

Modifichiamo Task.php che contiene il nostro oggetto:


<?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;
    }
}

Notare:

– l’utilizzo del namspace

use Symfony\Component\Validator\Constraints as Assert;

– la notazione per la validazione:


     /**
     * @Assert\NotBlank()
     * @Assert\EqualTo("Andrea")
     */

Per $task verrà accettato solamente un campo non vuoto ed uguale ad “Andrea”
Se tento di inviare un campo vuoto o diverso da “Andrea” sarà restituito il controllo di validazione

Si può consultare la lista completa dei controlli di validazione a:
symfony.com/doc/current/validation.html

Bibliografia:
symfony.com/doc/current/forms.html
symfony.com/doc/current/validation.html