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