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